|
1 (* |
|
2 * Hedgewars, a free turn based strategy game |
|
3 * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com> |
|
4 * |
|
5 * This program is free software; you can redistribute it and/or modify |
|
6 * it under the terms of the GNU General Public License as published by |
|
7 * the Free Software Foundation; version 2 of the License |
|
8 * |
|
9 * This program is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 * GNU General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU General Public License |
|
15 * along with this program; if not, write to the Free Software |
|
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
|
17 *) |
|
18 |
|
19 {$INCLUDE "options.inc"} |
|
20 unit uGearsList; |
|
21 |
|
22 interface |
|
23 uses uFloat, uTypes; |
|
24 |
|
25 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear; |
|
26 procedure DeleteGear(Gear: PGear); |
|
27 |
|
28 implementation |
|
29 |
|
30 uses uDebug, uRandom, uUtils, uConsts, uVariables, uAmmos, uTeams, uStats, |
|
31 uTextures, uScript, uRenderUtils, uAI, uCollisions, uGearsHedgehog; |
|
32 |
|
33 procedure InsertGearToList(Gear: PGear); |
|
34 var tmp, ptmp: PGear; |
|
35 begin |
|
36 tmp:= GearsList; |
|
37 ptmp:= GearsList; |
|
38 while (tmp <> nil) and (tmp^.Z <= Gear^.Z) do |
|
39 begin |
|
40 ptmp:= tmp; |
|
41 tmp:= tmp^.NextGear |
|
42 end; |
|
43 |
|
44 if ptmp <> tmp then |
|
45 begin |
|
46 Gear^.NextGear:= ptmp^.NextGear; |
|
47 Gear^.PrevGear:= ptmp; |
|
48 if ptmp^.NextGear <> nil then ptmp^.NextGear^.PrevGear:= Gear; |
|
49 ptmp^.NextGear:= Gear |
|
50 end |
|
51 else |
|
52 begin |
|
53 Gear^.NextGear:= GearsList; |
|
54 if Gear^.NextGear <> nil then Gear^.NextGear^.PrevGear:= Gear; |
|
55 GearsList:= Gear; |
|
56 end; |
|
57 end; |
|
58 |
|
59 procedure RemoveGearFromList(Gear: PGear); |
|
60 begin |
|
61 if Gear^.NextGear <> nil then Gear^.NextGear^.PrevGear:= Gear^.PrevGear; |
|
62 if Gear^.PrevGear <> nil then |
|
63 Gear^.PrevGear^.NextGear:= Gear^.NextGear |
|
64 else |
|
65 GearsList:= Gear^.NextGear |
|
66 end; |
|
67 |
|
68 function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear; |
|
69 const Counter: Longword = 0; |
|
70 var gear: PGear; |
|
71 begin |
|
72 inc(Counter); |
|
73 AddFileLog('AddGear: #' + inttostr(Counter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind)); |
|
74 |
|
75 New(gear); |
|
76 FillChar(gear^, sizeof(TGear), 0); |
|
77 gear^.X:= int2hwFloat(X); |
|
78 gear^.Y:= int2hwFloat(Y); |
|
79 gear^.Target.X:= NoPointX; |
|
80 gear^.Kind := Kind; |
|
81 gear^.State:= State; |
|
82 gear^.Active:= true; |
|
83 gear^.dX:= dX; |
|
84 gear^.dY:= dY; |
|
85 gear^.doStep:= doStepHandlers[Kind]; |
|
86 gear^.CollisionIndex:= -1; |
|
87 gear^.Timer:= Timer; |
|
88 gear^.FlightTime:= 0; |
|
89 gear^.uid:= Counter; |
|
90 gear^.SoundChannel:= -1; |
|
91 gear^.ImpactSound:= sndNone; |
|
92 gear^.nImpactSounds:= 0; |
|
93 gear^.Density:= _1; |
|
94 // Define ammo association, if any. |
|
95 gear^.AmmoType:= GearKindAmmoTypeMap[Kind]; |
|
96 if Ammoz[Gear^.AmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then gear^.Z:= cHHZ+1 |
|
97 else gear^.Z:= cUsualZ; |
|
98 |
|
99 if CurrentHedgehog <> nil then |
|
100 begin |
|
101 gear^.Hedgehog:= CurrentHedgehog; |
|
102 gear^.IntersectGear:= CurrentHedgehog^.Gear |
|
103 end; |
|
104 |
|
105 case Kind of |
|
106 gtGrenade, |
|
107 gtClusterBomb, |
|
108 gtGasBomb: begin |
|
109 gear^.ImpactSound:= sndGrenadeImpact; |
|
110 gear^.nImpactSounds:= 1; |
|
111 gear^.AdvBounce:= 1; |
|
112 gear^.Radius:= 5; |
|
113 gear^.Elasticity:= _0_8; |
|
114 gear^.Friction:= _0_8; |
|
115 gear^.Density:= _1_5; |
|
116 gear^.RenderTimer:= true; |
|
117 if gear^.Timer = 0 then gear^.Timer:= 3000 |
|
118 end; |
|
119 gtWatermelon: begin |
|
120 gear^.ImpactSound:= sndMelonImpact; |
|
121 gear^.nImpactSounds:= 1; |
|
122 gear^.AdvBounce:= 1; |
|
123 gear^.Radius:= 6; |
|
124 gear^.Elasticity:= _0_8; |
|
125 gear^.Friction:= _0_995; |
|
126 gear^.Density:= _2; |
|
127 gear^.RenderTimer:= true; |
|
128 if gear^.Timer = 0 then gear^.Timer:= 3000 |
|
129 end; |
|
130 gtMelonPiece: begin |
|
131 gear^.Density:= _2; |
|
132 end; |
|
133 gtHedgehog: begin |
|
134 gear^.AdvBounce:= 1; |
|
135 gear^.Radius:= cHHRadius; |
|
136 gear^.Elasticity:= _0_35; |
|
137 gear^.Friction:= _0_999; |
|
138 gear^.Angle:= cMaxAngle div 2; |
|
139 gear^.Density:= _3; |
|
140 gear^.Z:= cHHZ; |
|
141 if (GameFlags and gfAISurvival) <> 0 then |
|
142 if gear^.Hedgehog^.BotLevel > 0 then |
|
143 gear^.Hedgehog^.Effects[heResurrectable] := true; |
|
144 end; |
|
145 gtShell: begin |
|
146 gear^.Radius:= 4; |
|
147 gear^.Density:= _1; |
|
148 end; |
|
149 gtSnowball: begin |
|
150 gear^.ImpactSound:= sndMudballImpact; |
|
151 gear^.nImpactSounds:= 1; |
|
152 gear^.Radius:= 4; |
|
153 gear^.Elasticity:= _1; |
|
154 gear^.Friction:= _1; |
|
155 gear^.Density:= _0_5; |
|
156 end; |
|
157 |
|
158 gtFlake: begin |
|
159 with Gear^ do |
|
160 begin |
|
161 Pos:= 0; |
|
162 Radius:= 1; |
|
163 DirAngle:= random * 360; |
|
164 if State and gstTmpFlag = 0 then |
|
165 begin |
|
166 dx.isNegative:= GetRandom(2) = 0; |
|
167 dx.QWordValue:= GetRandom(100000000); |
|
168 dy.isNegative:= false; |
|
169 dy.QWordValue:= GetRandom(70000000); |
|
170 if GetRandom(2) = 0 then dx := -dx |
|
171 end; |
|
172 State:= State or gstInvisible; |
|
173 Health:= random(vobFrameTicks); |
|
174 Timer:= random(vobFramesCount); |
|
175 Angle:= (random(2) * 2 - 1) * (1 + random(10000)) * vobVelocity |
|
176 end |
|
177 end; |
|
178 gtGrave: begin |
|
179 gear^.ImpactSound:= sndGraveImpact; |
|
180 gear^.nImpactSounds:= 1; |
|
181 gear^.Radius:= 10; |
|
182 gear^.Elasticity:= _0_6; |
|
183 end; |
|
184 gtBee: begin |
|
185 gear^.Radius:= 5; |
|
186 gear^.Timer:= 500; |
|
187 gear^.RenderTimer:= true; |
|
188 gear^.Elasticity:= _0_9; |
|
189 gear^.Tag:= 0; |
|
190 end; |
|
191 gtSeduction: begin |
|
192 gear^.Radius:= 250; |
|
193 end; |
|
194 gtShotgunShot: begin |
|
195 gear^.Timer:= 900; |
|
196 gear^.Radius:= 2 |
|
197 end; |
|
198 gtPickHammer: begin |
|
199 gear^.Radius:= 10; |
|
200 gear^.Timer:= 4000 |
|
201 end; |
|
202 gtHammerHit: begin |
|
203 gear^.Radius:= 8; |
|
204 gear^.Timer:= 125 |
|
205 end; |
|
206 gtRope: begin |
|
207 gear^.Radius:= 3; |
|
208 gear^.Friction:= _450 * _0_01 * cRopePercent; |
|
209 RopePoints.Count:= 0; |
|
210 end; |
|
211 gtMine: begin |
|
212 gear^.ImpactSound:= sndMineImpact; |
|
213 gear^.nImpactSounds:= 1; |
|
214 gear^.Health:= 10; |
|
215 gear^.State:= gear^.State or gstMoving; |
|
216 gear^.Radius:= 2; |
|
217 gear^.Elasticity:= _0_55; |
|
218 gear^.Friction:= _0_995; |
|
219 gear^.Density:= _0_9; |
|
220 if cMinesTime < 0 then |
|
221 gear^.Timer:= getrandom(51)*100 |
|
222 else |
|
223 gear^.Timer:= cMinesTime; |
|
224 end; |
|
225 gtSMine: begin |
|
226 gear^.Health:= 10; |
|
227 gear^.State:= gear^.State or gstMoving; |
|
228 gear^.Radius:= 2; |
|
229 gear^.Elasticity:= _0_55; |
|
230 gear^.Friction:= _0_995; |
|
231 gear^.Density:= _0_9; |
|
232 gear^.Timer:= 500; |
|
233 end; |
|
234 gtCase: begin |
|
235 gear^.ImpactSound:= sndGraveImpact; |
|
236 gear^.nImpactSounds:= 1; |
|
237 gear^.Radius:= 16; |
|
238 gear^.Elasticity:= _0_3 |
|
239 end; |
|
240 gtExplosives: begin |
|
241 gear^.ImpactSound:= sndGrenadeImpact; |
|
242 gear^.nImpactSounds:= 1; |
|
243 gear^.Radius:= 16; |
|
244 gear^.Elasticity:= _0_4; |
|
245 gear^.Friction:= _0_995; |
|
246 gear^.Density:= _6; |
|
247 gear^.Health:= cBarrelHealth; |
|
248 gear^.Z:= cHHZ-1 |
|
249 end; |
|
250 gtDEagleShot: begin |
|
251 gear^.Radius:= 1; |
|
252 gear^.Health:= 50 |
|
253 end; |
|
254 gtSniperRifleShot: begin |
|
255 gear^.Radius:= 1; |
|
256 gear^.Health:= 50 |
|
257 end; |
|
258 gtDynamite: begin |
|
259 gear^.Radius:= 3; |
|
260 gear^.Elasticity:= _0_55; |
|
261 gear^.Friction:= _0_03; |
|
262 gear^.Density:= _2; |
|
263 gear^.Timer:= 5000; |
|
264 end; |
|
265 gtCluster: begin |
|
266 gear^.Radius:= 2; |
|
267 gear^.Density:= _1_5; |
|
268 gear^.RenderTimer:= true |
|
269 end; |
|
270 gtShover: gear^.Radius:= 20; |
|
271 gtFlame: begin |
|
272 gear^.Tag:= GetRandom(32); |
|
273 gear^.Radius:= 1; |
|
274 gear^.Health:= 5; |
|
275 gear^.Density:= _1; |
|
276 if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then |
|
277 begin |
|
278 gear^.dY:= (getrandom - _0_8) * _0_03; |
|
279 gear^.dX:= (getrandom - _0_5) * _0_4 |
|
280 end |
|
281 end; |
|
282 gtFirePunch: begin |
|
283 gear^.Radius:= 15; |
|
284 gear^.Tag:= Y |
|
285 end; |
|
286 gtAirBomb: begin |
|
287 gear^.Radius:= 5; |
|
288 gear^.Density:= _2; |
|
289 end; |
|
290 gtBlowTorch: begin |
|
291 gear^.Radius:= cHHRadius + cBlowTorchC; |
|
292 gear^.Timer:= 7500 |
|
293 end; |
|
294 gtSwitcher: begin |
|
295 gear^.Z:= cCurrHHZ |
|
296 end; |
|
297 gtTarget: begin |
|
298 gear^.ImpactSound:= sndGrenadeImpact; |
|
299 gear^.nImpactSounds:= 1; |
|
300 gear^.Radius:= 10; |
|
301 gear^.Elasticity:= _0_3; |
|
302 gear^.Timer:= 0 |
|
303 end; |
|
304 gtTardis: begin |
|
305 gear^.Timer:= 0; |
|
306 gear^.Pos:= 1; |
|
307 gear^.Z:= cCurrHHZ+1; |
|
308 end; |
|
309 gtMortar: begin |
|
310 gear^.Radius:= 4; |
|
311 gear^.Elasticity:= _0_2; |
|
312 gear^.Friction:= _0_08; |
|
313 gear^.Density:= _1; |
|
314 end; |
|
315 gtWhip: gear^.Radius:= 20; |
|
316 gtHammer: gear^.Radius:= 20; |
|
317 gtKamikaze: begin |
|
318 gear^.Health:= 2048; |
|
319 gear^.Radius:= 20 |
|
320 end; |
|
321 gtCake: begin |
|
322 gear^.Health:= 2048; |
|
323 gear^.Radius:= 7; |
|
324 gear^.Z:= cOnHHZ; |
|
325 gear^.RenderTimer:= true; |
|
326 gear^.DirAngle:= -90 * hwSign(Gear^.dX); |
|
327 if not dX.isNegative then gear^.Angle:= 1 else gear^.Angle:= 3 |
|
328 end; |
|
329 gtHellishBomb: begin |
|
330 gear^.ImpactSound:= sndHellishImpact1; |
|
331 gear^.nImpactSounds:= 4; |
|
332 gear^.AdvBounce:= 1; |
|
333 gear^.Radius:= 4; |
|
334 gear^.Elasticity:= _0_5; |
|
335 gear^.Friction:= _0_96; |
|
336 gear^.Density:= _1_5; |
|
337 gear^.RenderTimer:= true; |
|
338 gear^.Timer:= 5000 |
|
339 end; |
|
340 gtDrill: begin |
|
341 if gear^.Timer = 0 then gear^.Timer:= 5000; |
|
342 // Tag for drill strike. if 1 then first impact occured already |
|
343 gear^.Tag := 0; |
|
344 gear^.Radius:= 4; |
|
345 gear^.Density:= _1; |
|
346 end; |
|
347 gtBall: begin |
|
348 gear^.ImpactSound:= sndGrenadeImpact; |
|
349 gear^.nImpactSounds:= 1; |
|
350 gear^.AdvBounce:= 1; |
|
351 gear^.Radius:= 5; |
|
352 gear^.Tag:= random(8); |
|
353 gear^.Timer:= 5000; |
|
354 gear^.Elasticity:= _0_7; |
|
355 gear^.Friction:= _0_995; |
|
356 gear^.Density:= _1_5; |
|
357 end; |
|
358 gtBallgun: begin |
|
359 gear^.Timer:= 5001; |
|
360 end; |
|
361 gtRCPlane: begin |
|
362 gear^.Timer:= 15000; |
|
363 gear^.Health:= 3; |
|
364 gear^.Radius:= 8 |
|
365 end; |
|
366 gtJetpack: begin |
|
367 gear^.Health:= 2000; |
|
368 gear^.Damage:= 100 |
|
369 end; |
|
370 gtMolotov: begin |
|
371 gear^.Radius:= 6; |
|
372 gear^.Density:= _2; |
|
373 end; |
|
374 gtBirdy: begin |
|
375 gear^.Radius:= 16; // todo: check |
|
376 gear^.Timer:= 0; |
|
377 gear^.Health := 2000; |
|
378 gear^.FlightTime := 2; |
|
379 end; |
|
380 gtEgg: begin |
|
381 gear^.Radius:= 4; |
|
382 gear^.Elasticity:= _0_6; |
|
383 gear^.Friction:= _0_96; |
|
384 gear^.Density:= _1; |
|
385 if gear^.Timer = 0 then gear^.Timer:= 3000 |
|
386 end; |
|
387 gtPortal: begin |
|
388 gear^.ImpactSound:= sndMelonImpact; |
|
389 gear^.nImpactSounds:= 1; |
|
390 gear^.AdvBounce:= 0; |
|
391 gear^.Radius:= 17; |
|
392 // set color |
|
393 gear^.Tag:= 2 * gear^.Timer; |
|
394 gear^.Timer:= 15000; |
|
395 gear^.RenderTimer:= false; |
|
396 gear^.Health:= 100; |
|
397 end; |
|
398 gtPiano: begin |
|
399 gear^.Radius:= 32; |
|
400 gear^.Density:= _50; |
|
401 end; |
|
402 gtSineGunShot: begin |
|
403 gear^.Radius:= 5; |
|
404 gear^.Health:= 6000; |
|
405 end; |
|
406 gtFlamethrower: begin |
|
407 gear^.Tag:= 10; |
|
408 gear^.Timer:= 10; |
|
409 gear^.Health:= 500; |
|
410 gear^.Damage:= 100; |
|
411 end; |
|
412 gtLandGun: begin |
|
413 gear^.Tag:= 10; |
|
414 gear^.Timer:= 10; |
|
415 gear^.Health:= 1000; |
|
416 gear^.Damage:= 100; |
|
417 end; |
|
418 gtPoisonCloud: begin |
|
419 gear^.Timer:= 5000; |
|
420 gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000; |
|
421 end; |
|
422 gtResurrector: begin |
|
423 gear^.Radius := 100; |
|
424 gear^.Tag := 0 |
|
425 end; |
|
426 gtWaterUp: begin |
|
427 gear^.Tag := 47; |
|
428 end; |
|
429 gtNapalmBomb: begin |
|
430 gear^.Timer:= 1000; |
|
431 gear^.Radius:= 5; |
|
432 gear^.Density:= _1_5; |
|
433 end; |
|
434 gtStructure: begin |
|
435 gear^.Elasticity:= _0_55; |
|
436 gear^.Friction:= _0_995; |
|
437 gear^.Density:= _0_9; |
|
438 gear^.Radius:= 13; |
|
439 gear^.Health:= 200; |
|
440 gear^.Tag:= 3; |
|
441 end; |
|
442 end; |
|
443 |
|
444 InsertGearToList(gear); |
|
445 AddGear:= gear; |
|
446 |
|
447 ScriptCall('onGearAdd', gear^.uid); |
|
448 end; |
|
449 |
|
450 procedure DeleteGear(Gear: PGear); |
|
451 var team: PTeam; |
|
452 t,i: Longword; |
|
453 k: boolean; |
|
454 begin |
|
455 |
|
456 ScriptCall('onGearDelete', gear^.uid); |
|
457 |
|
458 DeleteCI(Gear); |
|
459 |
|
460 FreeTexture(Gear^.Tex); |
|
461 Gear^.Tex:= nil; |
|
462 |
|
463 // make sure that portals have their link removed before deletion |
|
464 if (Gear^.Kind = gtPortal) then |
|
465 begin |
|
466 if (Gear^.IntersectGear <> nil) then |
|
467 if (Gear^.IntersectGear^.IntersectGear = Gear) then |
|
468 Gear^.IntersectGear^.IntersectGear:= nil; |
|
469 end |
|
470 else if Gear^.Kind = gtHedgehog then |
|
471 (* |
|
472 This behaviour dates back to revision 4, and I accidentally encountered it with TARDIS. I don't think it must apply to any modern weapon, since if it was actually hit, the best the gear could do would be to destroy itself immediately, and you'd still end up with two graves. I believe it should be removed |
|
473 if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then |
|
474 begin |
|
475 AttackBar:= 0; |
|
476 Gear^.Message:= gmDestroy; |
|
477 CurAmmoGear^.Message:= gmDestroy; |
|
478 exit |
|
479 end |
|
480 else*) |
|
481 begin |
|
482 if (hwRound(Gear^.Y) >= cWaterLine) then |
|
483 begin |
|
484 t:= max(Gear^.Damage, Gear^.Health); |
|
485 Gear^.Damage:= t; |
|
486 if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF))) and (hwRound(Gear^.Y) < cWaterLine + 256) then |
|
487 spawnHealthTagForHH(Gear, t); |
|
488 end; |
|
489 |
|
490 team:= Gear^.Hedgehog^.Team; |
|
491 if CurrentHedgehog^.Gear = Gear then |
|
492 begin |
|
493 AttackBar:= 0; |
|
494 FreeActionsList; // to avoid ThinkThread on drawned gear |
|
495 if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (CurrentHedgehog^.MultiShootAttacks > 0) then OnUsedAmmo(CurrentHedgehog^); |
|
496 end; |
|
497 |
|
498 Gear^.Hedgehog^.Gear:= nil; |
|
499 if Gear^.Hedgehog^.King then |
|
500 begin |
|
501 // are there any other kings left? Just doing nil check. Presumably a mortally wounded king will get reaped soon enough |
|
502 k:= false; |
|
503 for i:= 0 to Pred(team^.Clan^.TeamsNumber) do |
|
504 if (team^.Clan^.Teams[i]^.Hedgehogs[0].Gear <> nil) then k:= true; |
|
505 if not k then |
|
506 for i:= 0 to Pred(team^.Clan^.TeamsNumber) do |
|
507 begin |
|
508 team^.Clan^.Teams[i]^.hasGone:= true; |
|
509 TeamGoneEffect(team^.Clan^.Teams[i]^) |
|
510 end |
|
511 end; |
|
512 |
|
513 // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog |
|
514 // same stand for CheckHHDamage |
|
515 if (Gear^.LastDamage <> nil) then |
|
516 uStats.HedgehogDamaged(Gear, Gear^.LastDamage, 0, true) |
|
517 else |
|
518 uStats.HedgehogDamaged(Gear, CurrentHedgehog, 0, true); |
|
519 |
|
520 inc(KilledHHs); |
|
521 RecountTeamHealth(team); |
|
522 if (CurrentHedgehog <> nil) and CurrentHedgehog^.Effects[heResurrectable] and (not Gear^.Hedgehog^.Effects[heResurrectable]) then |
|
523 with CurrentHedgehog^ do |
|
524 begin |
|
525 inc(Team^.stats.AIKills); |
|
526 FreeTexture(Team^.AIKillsTex); |
|
527 Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16); |
|
528 end |
|
529 end; |
|
530 with Gear^ do |
|
531 AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind)); |
|
532 |
|
533 if CurAmmoGear = Gear then CurAmmoGear:= nil; |
|
534 if FollowGear = Gear then FollowGear:= nil; |
|
535 if lastGearByUID = Gear then lastGearByUID := nil; |
|
536 RemoveGearFromList(Gear); |
|
537 Dispose(Gear) |
|
538 end; |
|
539 |
|
540 end. |