Skip to content

Commit 2e3f722

Browse files
committed
Refines Grapple Gun mechanics and rope physics
- Increases grapple maximum line length for extended reach. - Adjusts grapple's initial velocity to fully inherit parent's velocity. - Enhances parent gun detection radius. - Re-enables logic to set last segment positions, affecting in-flight rope behavior. - Improves rope physics stability by preventing potential division by zero errors. - Dynamically optimizes physics iterations in rope simulation. - Corrects rope segment distance calculation in constraint application.
1 parent f842201 commit 2e3f722

File tree

2 files changed

+30
-32
lines changed

2 files changed

+30
-32
lines changed

Data/Base.rte/Devices/Tools/GrappleGun/Grapple.lua

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function Create(self)
2121
self.canTap = false
2222

2323
self.fireVel = 40 -- This immediately overwrites the .ini FireVel
24-
self.maxLineLength = 400 -- Shorter rope for faster gameplay
24+
self.maxLineLength = 600 -- Shorter rope for faster gameplay (Increased from 400)
2525
self.maxShootDistance = self.maxLineLength * 0.95 -- 95% of maxLineLength (5% less shooting distance)
2626
self.setLineLength = 0
2727
self.lineStrength = 10000 -- EXTREMELY HIGH force threshold - virtually unbreakable (was 120)
@@ -81,7 +81,7 @@ function Create(self)
8181

8282
--Find the parent gun that fired us
8383
for gun in MovableMan:GetMOsInRadius(self.Pos, 50) do
84-
if gun and gun.ClassName == "HDFirearm" and gun.PresetName == "Grapple Gun" and SceneMan:ShortestDistance(self.Pos, ToHDFirearm(gun).MuzzlePos, self.mapWrapsX):MagnitudeIsLessThan(5) then
84+
if gun and gun.ClassName == "HDFirearm" and gun.PresetName == "Grapple Gun" and SceneMan:ShortestDistance(self.Pos, ToHDFirearm(gun).MuzzlePos, self.mapWrapsX):MagnitudeIsLessThan(15) then -- Increased threshold from 5 to 15
8585
self.parentGun = ToHDFirearm(gun)
8686
self.parent = MovableMan:GetMOFromID(gun.RootID)
8787
if MovableMan:IsActor(self.parent) then
@@ -92,7 +92,7 @@ function Create(self)
9292
self.parent = ToACrab(self.parent)
9393
end
9494

95-
self.Vel = (self.parent.Vel * 0.5) + Vector(self.fireVel, 0):RadRotate(self.parent:GetAimAngle(true))
95+
self.Vel = self.parent.Vel + Vector(self.fireVel, 0):RadRotate(self.parent:GetAimAngle(true)) -- Changed: Use full parent velocity
9696
self.parentGun:RemoveNumberValue("GrappleMode")
9797
for part in self.parent.Attachables do
9898
local radcheck = SceneMan:ShortestDistance(self.parent.Pos, part.Pos, self.mapWrapsX).Magnitude + part.Radius
@@ -135,7 +135,7 @@ function Update(self)
135135
self.lineLength = self.lineVec.Magnitude
136136
self.currentLineLength = self.lineLength
137137

138-
-- Check if we\'ve reached the maximum shooting distance during flight
138+
-- Check if we've reached the maximum shooting distance during flight
139139
if self.lineLength >= self.maxShootDistance then
140140
-- Stop the claw at max shooting distance but keep it in flight mode
141141
local maxShootVec = self.lineVec:SetMagnitude(self.maxShootDistance)
@@ -154,11 +154,10 @@ function Update(self)
154154
self.apy[self.currentSegments] = self.Pos.Y
155155

156156
-- Set all lastX/lastY positions to prevent velocity inheritance from previous mode
157-
-- Commenting out this loop allows for rope physics during flight
158-
-- for i = 0, self.currentSegments do
159-
-- self.lastX[i] = self.apx[i]
160-
-- self.lastY[i] = self.apy[i]
161-
-- end
157+
for i = 0, self.currentSegments do
158+
self.lastX[i] = self.apx[i]
159+
self.lastY[i] = self.apy[i]
160+
end
162161
end
163162

164163
-- Calculate optimal number of segments based on rope length using our module function
@@ -180,18 +179,18 @@ function Update(self)
180179

181180
-- Apply constraints and check for rope breaking (extremely high threshold)
182181
local ropeBreaks = RopePhysics.applyRopeConstraints(self, self.currentLineLength)
183-
if ropeBreaks or self.shouldBreak then
184-
-- Rope snapped due to EXTREME tension (500% stretch)
185-
self.ToDelete = true
186-
if self.parent and self.parent:IsPlayerControlled() then
187-
-- Add screen shake and sound effect when rope breaks
188-
FrameMan:SetScreenScrollSpeed(10.0) -- More dramatic shake for extreme break
189-
if self.returnSound then
190-
self.returnSound:Play(self.parent.Pos)
182+
if ropeBreaks or self.shouldBreak then
183+
-- Rope snapped due to EXTREME tension (500% stretch)
184+
self.ToDelete = true
185+
if self.parent and self.parent:IsPlayerControlled() then
186+
-- Add screen shake and sound effect when rope breaks
187+
FrameMan:SetScreenScrollSpeed(10.0) -- More dramatic shake for extreme break
188+
if self.returnSound then
189+
self.returnSound:Play(self.parent.Pos)
190+
end
191191
end
192+
return -- Exit early since rope is breaking
192193
end
193-
return -- Exit early since rope is breaking
194-
end
195194

196195
-- Special handling for attached targets (MO grabbing)
197196
if self.actionMode == 3 and self.target and self.target.ID ~= rte.NoMOID then
@@ -391,16 +390,16 @@ function Update(self)
391390
self.returnSound:Play(self.parent.Pos)
392391
end
393392

394-
else
395-
self.ToDelete = true -- Parent Actor has no controller
393+
else -- Parent Actor has no controller
394+
self.ToDelete = true
396395
end
397-
else
398-
self.ToDelete = true -- Parent is not an Actor
399-
end
400-
else
396+
else -- else for 'if MovableMan:IsActor(self.parent) then'
397+
self.ToDelete = true
398+
end -- end for 'if MovableMan:IsActor(self.parent) then'
399+
else -- else for 'if self.parent and IsMOSRotating(self.parent) and self.parent:HasObject("Grapple Gun") then'
401400
self.ToDelete = true -- Parent is nil, not MOSRotating, or doesn't have "Grapple Gun"
402-
end
403-
end
401+
end -- end for 'if self.parent and IsMOSRotating(self.parent) and self.parent:HasObject("Grapple Gun") then'
402+
end -- end for 'function Update(self)'
404403

405404
function Destroy(self)
406405
if MovableMan:IsParticle(self.crankSound) then

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
-- filepath: /home/cretin/git/Cortex-Command-Community-Project/Data/Base.rte/Devices/Tools/GrappleGun/Scripts/RopePhysics.lua
21
--[[
32
RopePhysics.lua - Advanced Rope Physics Module
43
@@ -444,7 +443,7 @@ function RopePhysics.applyRopeConstraints(grappleInstance, currentTotalCableLeng
444443
currentActualLength = currentActualLength + math.sqrt(dx*dx + dy*dy)
445444
end
446445

447-
if currentActualLength > maxRopeLength then
446+
if currentActualLength > 0.001 and currentActualLength > maxRopeLength then -- Added check for currentActualLength > 0.001
448447
-- Rope needs to be shortened - apply smooth contraction
449448
local contractionRatio = maxRopeLength / currentActualLength
450449
local contractionSpeed = 0.1 -- Smooth retraction speed
@@ -468,8 +467,8 @@ function RopePhysics.applyRopeConstraints(grappleInstance, currentTotalCableLeng
468467

469468
-- THIRD: Apply rigid Verlet constraints for rope segments using MAXIMUM ALLOWED length
470469
-- This prevents gradual stretching during swinging by enforcing the max rope length
471-
local targetSegmentLength = maxRopeLength / segments -- Use maximum allowed length, not current distance
472-
local iterations = 32 -- High iteration count for rigid rope behavior
470+
local targetSegmentLength = maxRopeLength / math.max(1, segments) -- Use maximum allowed length, not current distance, ensure segments is not zero
471+
local iterations = RopePhysics.optimizePhysicsIterations(grappleInstance) -- Dynamically set iterations
473472
local constraint_strength = 1.0 -- Full strength for completely rigid rope
474473

475474
for iter = 1, iterations do
@@ -482,7 +481,7 @@ function RopePhysics.applyRopeConstraints(grappleInstance, currentTotalCableLeng
482481

483482
local dx = x2 - x1
484483
local dy = y2 - y1
485-
local distance = math.sqrt(dx*dx + dy*dy)
484+
local distance = math.sqrt(dx*dx + dy*dy) -- Reverted: Removed * 1.5 multiplier
486485

487486
if distance > 0.001 then -- Avoid division by zero
488487
-- Calculate exact constraint satisfaction

0 commit comments

Comments
 (0)