@@ -27,7 +27,7 @@ function Create(self)
27
27
28
28
self .limitReached = false
29
29
self .stretchMode = false -- Alternative elastic pull mode a là Liero
30
- self .stretchPullRatio = 0.1
30
+ self .stretchPullRatio = 0.01 -- How much the rope stretches when pulling in stretch mode
31
31
self .pieSelection = 0 -- 0 is nothing, 1 is full retract, 2 is partial retract, 3 is partial extend, 4 is full extend
32
32
33
33
self .climbDelay = 8 -- Faster climbing for shorter rope
@@ -48,8 +48,8 @@ function Create(self)
48
48
self .cablespring = 0.15 -- VelvetGrapple constraint stiffness
49
49
50
50
-- Dynamic rope segment calculation variables
51
- self .minSegments = 4 -- Minimum number of segments
52
- self .maxSegments = 50 -- Maximum number of segments
51
+ self .minSegments = 1 -- Minimum number of segments
52
+ self .maxSegments = 500 -- Maximum number of segments
53
53
self .segmentLength = 12 -- Target length per segment (increased for better performance)
54
54
self .currentSegments = self .minSegments -- Current number of segments
55
55
@@ -137,11 +137,17 @@ function Update(self)
137
137
self .lineLength = self .lineVec .Magnitude
138
138
self .currentLineLength = self .lineLength
139
139
140
- -- Update rope anchor points directly
140
+ -- Update rope anchor points directly for flight mode
141
141
self .apx [0 ] = self .parent .Pos .X
142
142
self .apy [0 ] = self .parent .Pos .Y
143
143
self .apx [self .currentSegments ] = self .Pos .X
144
144
self .apy [self .currentSegments ] = self .Pos .Y
145
+
146
+ -- Set all lastX/lastY positions to prevent velocity inheritance from previous mode
147
+ for i = 0 , self .currentSegments do
148
+ self .lastX [i ] = self .apx [i ]
149
+ self .lastY [i ] = self .apy [i ]
150
+ end
145
151
end
146
152
147
153
-- Calculate optimal number of segments based on rope length using our module function
@@ -155,75 +161,46 @@ function Update(self)
155
161
end
156
162
end
157
163
158
- -- Rope physics simulation using VelvetGrapple approach
159
- local cablelength = self .currentLineLength / math.max ( 1 , self . currentSegments ) -- Dynamic per-segment length
164
+ -- Proper rope physics simulation using the RopePhysics module
165
+ local endPos = self .Pos
160
166
161
- -- Set anchor points and update physics for all segments
162
- local i = self .currentSegments
163
- -- HANDLE ALL LINE JOINTS (from n down to 0)
164
- while i > - 1 do
165
- if i == 0 or (i == self .currentSegments and self .limitReached == false and (self .actionMode == 1 or self .actionMode > 1 )) then
166
- -- Anchor points: 0 (player) and n (hook)
167
- if i == 0 then -- POINT 0: ANCHOR TO GUN
168
- local usepos = self .parent .Pos
169
- self .apx [i ] = usepos .X
170
- self .apy [i ] = usepos .Y
171
- self .lastX [i ] = self .lastPos .X
172
- self .lastY [i ] = self .lastPos .Y
173
- else -- POINT n: ANCHOR TO GRAPPLE if IN FLIGHT
174
- local usepos = self .Pos
175
- self .apx [i ] = usepos .X
176
- self .apy [i ] = usepos .Y
177
- self .lastX [i ] = usepos .X
178
- self .lastY [i ] = usepos .Y
179
- end
180
- else
181
- if not (i == self .currentSegments and self .actionMode == 2 ) then
182
- -- CALCULATE BASIC PHYSICS
183
- local accX = 0
184
- local accY = 0.05
185
-
186
- local velX = self .apx [i ] - self .lastX [i ]
187
- local velY = self .apy [i ] - self .lastY [i ]
188
-
189
- local ufriction = self .usefriction
190
- if i == self .currentSegments then
191
- ufriction = 0.99
192
- accY = 0.5
193
- end
194
-
195
- local nextX = (velX + accX ) * ufriction
196
- local nextY = (velY + accY ) * ufriction
197
-
198
- self .lastX [i ] = self .apx [i ]
199
- self .lastY [i ] = self .apy [i ]
200
-
201
- -- Use physics module for collision handling
202
- RopePhysics .verletCollide (self , i , nextX , nextY )
203
- end
204
-
205
- if i == self .currentSegments and self .actionMode == 3 then
206
- if self .target and self .target .ID ~= rte .NoMOID then
207
- local target = self .target
208
- if target .ID ~= target .RootID then
209
- local mo = target :GetRootParent ()
210
- if mo .ID ~= rte .NoMOID and IsAttachable (target ) then
211
- target = mo
212
- end
213
- end
214
-
215
- self .lastX [i ] = self .apx [i ]- target .Vel .X
216
- self .lastY [i ] = self .apy [i ]- target .Vel .Y
217
- else -- Our MO has been destroyed, return hook
218
- self .ToDelete = true
219
- end
167
+ -- Choose physics simulation based on rope mode
168
+ if self .actionMode == 1 then
169
+ -- Flight mode - keep rope tight and straight
170
+ RopePhysics .updateRopeFlightPath (self )
171
+ else
172
+ -- Attached mode - run full physics simulation
173
+ RopePhysics .updateRopePhysics (self , startPos , endPos , self .currentLineLength )
174
+
175
+ -- Apply constraints to maintain rope structure and length
176
+ RopePhysics .applyRopeConstraints (self , self .currentLineLength )
177
+ end
178
+
179
+ -- Special handling for attached targets (MO grabbing)
180
+ if self .actionMode == 3 and self .target and self .target .ID ~= rte .NoMOID then
181
+ local target = self .target
182
+ if target .ID ~= target .RootID then
183
+ local mo = target :GetRootParent ()
184
+ if mo .ID ~= rte .NoMOID and IsAttachable (target ) then
185
+ target = mo
220
186
end
221
187
end
222
188
223
- -- Get optimized iteration count based on rope conditions
224
- local maxIterations = RopePhysics .optimizePhysicsIterations (self )
225
-
226
- i = i - 1
189
+ -- Update hook position to follow the target
190
+ self .Pos = target .Pos
191
+ self .apx [self .currentSegments ] = target .Pos .X
192
+ self .apy [self .currentSegments ] = target .Pos .Y
193
+
194
+ -- Apply target velocity to the hook anchor for physics continuity
195
+ self .lastX [self .currentSegments ] = self .apx [self .currentSegments ] - target .Vel .X
196
+ self .lastY [self .currentSegments ] = self .apy [self .currentSegments ] - target .Vel .Y
197
+ else
198
+ -- Update hook position from rope physics when not attached to MO
199
+ if self .actionMode > 1 then -- Hook is stuck to terrain
200
+ -- Let the rope physics determine hook position constraints
201
+ self .Pos .X = self .apx [self .currentSegments ]
202
+ self .Pos .Y = self .apy [self .currentSegments ]
203
+ end
227
204
end
228
205
229
206
-- Draw the rope using the renderer module
@@ -236,19 +213,23 @@ function Update(self)
236
213
local debugPos = self .Pos + Vector (10 , - 30 ) -- Define a position for debug text
237
214
RopeRenderer .showDebugInfo (self , player , debugPos )
238
215
239
- -- Update hook position based on rope physics
216
+ -- Update lineVec and lineLength based on current positions
217
+ self .lineVec = SceneMan :ShortestDistance (self .parent .Pos , self .Pos , self .mapWrapsX )
218
+ self .lineLength = self .lineVec .Magnitude
219
+
220
+ -- Update hook position if length limit is reached during flight
240
221
if self .actionMode == 1 and self .limitReached == true then
241
222
self .Pos .X = self .apx [self .currentSegments ]
242
223
self .Pos .Y = self .apy [self .currentSegments ]
243
224
end
244
225
245
- self .lineVec = SceneMan :ShortestDistance (self .parent .Pos , self .Pos , self .mapWrapsX )
246
- self .lineLength = self .lineVec .Magnitude
247
-
248
- -- Update current line length
226
+ -- Update current line length based on action mode
249
227
if self .actionMode == 1 and self .limitReached == false then
250
- -- Always update rope length while in flight
228
+ -- Always update rope length while in flight - rope should be tight
251
229
self .currentLineLength = self .lineLength
230
+ elseif self .actionMode > 1 then
231
+ -- When attached, maintain set line length for physics constraints
232
+ -- currentLineLength should only be updated by player input or automatic climbing
252
233
end
253
234
254
235
-- Check if line length exceeds maximum
0 commit comments