branch | ui-scaling |
changeset 15288 | c4fd2813b127 |
parent 15283 | 16f389fcd462 |
child 15301 | b5171e6c94a4 |
13395:0135e64c6c66 | 15288:c4fd2813b127 |
---|---|
30 unit uGearsHandlersMess; |
30 unit uGearsHandlersMess; |
31 interface |
31 interface |
32 uses uTypes, uFloat; |
32 uses uTypes, uFloat; |
33 |
33 |
34 procedure doStepPerPixel(Gear: PGear; step: TGearStepProcedure; onlyCheckIfChanged: boolean); |
34 procedure doStepPerPixel(Gear: PGear; step: TGearStepProcedure; onlyCheckIfChanged: boolean); |
35 procedure makeHogsWorry(x, y: hwFloat; r: LongInt); |
35 procedure makeHogsWorry(x, y: hwFloat; r: LongInt; gearType: TGearType); |
36 procedure HideHog(HH: PHedgehog); |
36 procedure HideHog(HH: PHedgehog); |
37 procedure doStepDrowningGear(Gear: PGear); |
37 procedure doStepDrowningGear(Gear: PGear); |
38 procedure doStepFallingGear(Gear: PGear); |
38 procedure doStepFallingGear(Gear: PGear); |
39 procedure doStepBomb(Gear: PGear); |
39 procedure doStepBomb(Gear: PGear); |
40 procedure doStepMolotov(Gear: PGear); |
40 procedure doStepMolotov(Gear: PGear); |
113 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
113 procedure loadNewPortalBall(oldPortal: PGear; destroyGear: Boolean); |
114 procedure doStepMovingPortal_real(Gear: PGear); |
114 procedure doStepMovingPortal_real(Gear: PGear); |
115 procedure doStepMovingPortal(Gear: PGear); |
115 procedure doStepMovingPortal(Gear: PGear); |
116 procedure doStepPortalShot(newPortal: PGear); |
116 procedure doStepPortalShot(newPortal: PGear); |
117 procedure doStepPiano(Gear: PGear); |
117 procedure doStepPiano(Gear: PGear); |
118 procedure doStepPianoWork(Gear: PGear); |
|
118 procedure doStepSineGunShotWork(Gear: PGear); |
119 procedure doStepSineGunShotWork(Gear: PGear); |
119 procedure doStepSineGunShot(Gear: PGear); |
120 procedure doStepSineGunShot(Gear: PGear); |
120 procedure doStepFlamethrowerWork(Gear: PGear); |
121 procedure doStepFlamethrowerWork(Gear: PGear); |
121 procedure doStepFlamethrower(Gear: PGear); |
122 procedure doStepFlamethrower(Gear: PGear); |
122 procedure doStepLandGunWork(Gear: PGear); |
123 procedure doStepLandGunWork(Gear: PGear); |
126 procedure doStepHammerHitWork(Gear: PGear); |
127 procedure doStepHammerHitWork(Gear: PGear); |
127 procedure doStepHammerHit(Gear: PGear); |
128 procedure doStepHammerHit(Gear: PGear); |
128 procedure doStepResurrectorWork(Gear: PGear); |
129 procedure doStepResurrectorWork(Gear: PGear); |
129 procedure doStepResurrector(Gear: PGear); |
130 procedure doStepResurrector(Gear: PGear); |
130 procedure doStepNapalmBomb(Gear: PGear); |
131 procedure doStepNapalmBomb(Gear: PGear); |
131 //procedure doStepStructure(Gear: PGear); |
|
132 procedure doStepTardisWarp(Gear: PGear); |
132 procedure doStepTardisWarp(Gear: PGear); |
133 procedure doStepTardis(Gear: PGear); |
133 procedure doStepTardis(Gear: PGear); |
134 procedure updateFuel(Gear: PGear); |
134 procedure updateFuel(Gear: PGear); |
135 procedure updateTarget(Gear:PGear; newX, newY:HWFloat); |
135 procedure updateTarget(Gear:PGear; newX, newY:HWFloat); |
136 procedure doStepIceGun(Gear: PGear); |
136 procedure doStepIceGun(Gear: PGear); |
137 procedure doStepAddAmmo(Gear: PGear); |
137 procedure doStepAddAmmo(Gear: PGear); |
138 procedure doStepGenericFaller(Gear: PGear); |
138 procedure doStepGenericFaller(Gear: PGear); |
139 //procedure doStepCreeper(Gear: PGear); |
139 procedure doStepCreeper(Gear: PGear); |
140 procedure doStepKnife(Gear: PGear); |
140 procedure doStepKnife(Gear: PGear); |
141 procedure doStepDuck(Gear: PGear); |
|
142 procedure doStepMinigunWork(Gear: PGear); |
141 procedure doStepMinigunWork(Gear: PGear); |
143 procedure doStepMinigun(Gear: PGear); |
142 procedure doStepMinigun(Gear: PGear); |
144 procedure doStepMinigunBullet(Gear: PGear); |
143 procedure doStepMinigunBullet(Gear: PGear); |
145 |
144 |
146 var |
145 var |
200 or ((Gear^.State and gstMoving) = 0) then |
199 or ((Gear^.State and gstMoving) = 0) then |
201 break; |
200 break; |
202 end; |
201 end; |
203 end; |
202 end; |
204 |
203 |
205 procedure makeHogsWorry(x, y: hwFloat; r: LongInt); |
204 procedure makeHogsWorry(x, y: hwFloat; r: LongInt; gearType: TGearType); |
206 var |
205 var |
207 gi: PGear; |
206 gi: PGear; |
208 d: LongInt; |
207 d: LongInt; |
208 grenadeTaunt: boolean; |
|
209 begin |
209 begin |
210 gi := GearsList; |
210 gi := GearsList; |
211 while gi <> nil do |
211 while gi <> nil do |
212 begin |
212 begin |
213 if (gi^.Kind = gtHedgehog) then |
213 if (gi^.Kind = gtHedgehog) then |
214 begin |
214 begin |
215 d := r - hwRound(Distance(gi^.X - x, gi^.Y - y)); |
215 d := r - hwRound(Distance(gi^.X - x, gi^.Y - y)); |
216 if (d > 1) and (gi^.Hedgehog^.Effects[heInvulnerable] = 0) and (GetRandom(2) = 0) then |
216 if (d > 1) and (gi^.Hedgehog^.Effects[heInvulnerable] = 0) and (GetRandom(2) = 0) then |
217 begin |
217 begin |
218 if (CurrentHedgehog^.Gear = gi) then |
218 if (CurrentHedgehog^.Gear = gi) then |
219 PlaySoundV(sndOops, gi^.Hedgehog^.Team^.voicepack) |
219 if (CurrentHedgehog^.Gear^.FlightTime = 0) then |
220 case random(4) of |
|
221 0: PlaySoundV(sndWhatThe, gi^.Hedgehog^.Team^.voicepack); |
|
222 1: PlaySoundV(sndOops, gi^.Hedgehog^.Team^.voicepack); |
|
223 2: PlaySoundV(sndRunAway, gi^.Hedgehog^.Team^.voicepack); |
|
224 3: PlaySoundV(sndRunAway, gi^.Hedgehog^.Team^.voicepack); |
|
225 end |
|
226 else |
|
227 if random(4) = 0 then |
|
228 PlaySoundV(sndWhatThe, gi^.Hedgehog^.Team^.voicepack) |
|
229 else |
|
230 PlaySoundV(sndOops, gi^.Hedgehog^.Team^.voicepack) |
|
220 |
231 |
221 else |
232 else |
222 begin |
233 begin |
223 if ((gi^.State and gstMoving) = 0) and (gi^.Hedgehog^.Effects[heFrozen] = 0) then |
234 if ((gi^.State and gstMoving) = 0) and (gi^.Hedgehog^.Effects[heFrozen] = 0) then |
224 begin |
235 begin |
225 gi^.dX.isNegative:= X<gi^.X; |
236 gi^.dX.isNegative:= X<gi^.X; |
226 gi^.State := gi^.State or gstLoser; |
237 gi^.State := gi^.State or gstLoser; |
227 end; |
238 end; |
228 |
239 |
229 if d > r div 2 then |
240 grenadeTaunt:= false; |
230 PlaySoundV(sndNooo, gi^.Hedgehog^.Team^.voicepack) |
241 if (gearType = gtGrenade) then |
242 grenadeTaunt:= random(2) = 0; |
|
243 |
|
244 if grenadeTaunt then |
|
245 PlaySoundV(sndGrenade, gi^.Hedgehog^.Team^.voicepack) |
|
231 else |
246 else |
232 PlaySoundV(sndUhOh, gi^.Hedgehog^.Team^.voicepack); |
247 if d > r div 2 then |
248 if random(3) = 0 then |
|
249 PlaySoundV(sndWhatThe, gi^.Hedgehog^.Team^.voicepack) |
|
250 else |
|
251 PlaySoundV(sndNooo, gi^.Hedgehog^.Team^.voicepack) |
|
252 else |
|
253 PlaySoundV(sndUhOh, gi^.Hedgehog^.Team^.voicepack); |
|
254 |
|
233 end; |
255 end; |
234 end; |
256 end; |
235 end; |
257 end; |
236 |
258 |
237 gi := gi^.NextGear |
259 gi := gi^.NextGear |
285 |
307 |
286 Gear^.Y := Gear^.Y + cDrownSpeed; |
308 Gear^.Y := Gear^.Y + cDrownSpeed; |
287 |
309 |
288 if cWaterLine > hwRound(Gear^.Y) + Gear^.Radius then |
310 if cWaterLine > hwRound(Gear^.Y) + Gear^.Radius then |
289 begin |
311 begin |
290 if LongInt(leftX) + Gear^.Radius > hwRound(Gear^.X) then |
312 if leftX + Gear^.Radius > hwRound(Gear^.X) then |
291 Gear^.X := Gear^.X - cDrownSpeed |
313 Gear^.X := Gear^.X - cDrownSpeed |
292 else |
314 else |
293 Gear^.X := Gear^.X + cDrownSpeed; |
315 Gear^.X := Gear^.X + cDrownSpeed; |
294 end |
316 end |
295 else |
317 else |
305 or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then |
327 or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then |
306 if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then |
328 if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then |
307 AddVisualGear(bubbleX, bubbleY, vgtBubble) |
329 AddVisualGear(bubbleX, bubbleY, vgtBubble) |
308 else if Random(12) = 0 then |
330 else if Random(12) = 0 then |
309 AddVisualGear(bubbleX, bubbleY, vgtBubble); |
331 AddVisualGear(bubbleX, bubbleY, vgtBubble); |
332 // Insta-delete gear and skip drowning animation if water is 100% opaque |
|
310 if (not SuddenDeathDmg and (WaterOpacity > $FE)) |
333 if (not SuddenDeathDmg and (WaterOpacity > $FE)) |
311 or (SuddenDeathDmg and (SDWaterOpacity > $FE)) |
334 or (SuddenDeathDmg and (SDWaterOpacity > $FE)) then |
312 or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then |
335 begin |
336 // Teleport gear to a suitable position for the damage tag in the water |
|
337 if (WorldEdge = weSea) and (hwRound(Gear^.X) - Gear^.Radius < leftX) then |
|
338 begin |
|
339 if (hwRound(Gear^.X) - Gear^.Radius > leftX - 90) then |
|
340 Gear^.X := Gear^.X - _90 |
|
341 end |
|
342 else if (WorldEdge = weSea) and (hwRound(Gear^.X) + Gear^.Radius > rightX) then |
|
343 begin |
|
344 if (hwRound(Gear^.X) - Gear^.Radius < rightX + 90) then |
|
345 Gear^.X := Gear^.X + _90 |
|
346 end |
|
347 else |
|
348 Gear^.Y := int2hwFloat(Gear^.Radius + cWaterLine + cVisibleWater); |
|
349 DeleteGear(Gear); |
|
350 exit; |
|
351 end; |
|
352 // Delete gear normally if it is outside of visible range. |
|
353 // But first determine size tolerance for big gears to make sure the gear is REALLY out of range. |
|
354 if Gear^.Kind = gtPiano then |
|
355 d:= SpritesData[sprPiano].height |
|
356 else if Gear^.Kind = gtRCPlane then |
|
357 d:= SpritesData[sprPlane].width |
|
358 else if Gear^.Kind = gtKnife then |
|
359 d:= SpritesData[sprKnife].height |
|
360 else if Gear^.Kind = gtDynamite then |
|
361 d:= SpritesData[sprDynamite].height |
|
362 else if Gear^.Kind = gtSnowball then |
|
363 d:= SpritesData[sprSnowball].height |
|
364 else |
|
365 d:= Gear^.Radius * 2; |
|
366 if (hwRound(Gear^.Y) > d + cWaterLine + cVisibleWater) then |
|
313 DeleteGear(Gear); |
367 DeleteGear(Gear); |
314 end; |
368 end; |
315 |
369 |
316 //////////////////////////////////////////////////////////////////////////////// |
370 //////////////////////////////////////////////////////////////////////////////// |
317 procedure doStepFallingGear(Gear: PGear); |
371 procedure doStepFallingGear(Gear: PGear); |
318 var |
372 var |
319 isFalling: boolean; |
373 isFalling: boolean; |
320 //tmp: QWord; |
|
321 tX, tdX, tdY: hwFloat; |
374 tX, tdX, tdY: hwFloat; |
322 collV, collH, gX, gY: LongInt; |
375 collV, collH, gX, gY: LongInt; |
323 land, xland: word; |
376 land, xland: word; |
324 begin |
377 begin |
325 tX:= Gear^.X; |
378 tX:= Gear^.X; |
326 gX:= hwRound(Gear^.X); |
379 gX:= hwRound(Gear^.X); |
327 gY:= hwRound(Gear^.Y); |
380 gY:= hwRound(Gear^.Y); |
328 if (Gear^.Kind <> gtGenericFaller) and WorldWrap(Gear) and (WorldEdge = weWrap) and (Gear^.AdvBounce <> 0) and |
381 Gear^.State := Gear^.State and (not gstCollision); |
382 |
|
383 // World wrap |
|
384 if (Gear^.Kind <> gtGenericFaller) and WorldWrap(Gear) and (WorldEdge = weWrap) and |
|
329 ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0)) then |
385 ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0)) then |
330 begin |
386 begin |
331 Gear^.X:= tX; |
387 // Collision with land that *just* behind the other side of the world wrap edge |
332 Gear^.dX.isNegative:= (gX > LongInt(leftX) + Gear^.Radius*2) |
388 if (not Gear^.Sticky) then |
389 begin |
|
390 Gear^.X:= tX; |
|
391 Gear^.dX.isNegative:= (gX > leftX + Gear^.Radius*2); |
|
392 Gear^.dX := Gear^.dX * Gear^.Friction; |
|
393 end; |
|
394 Gear^.State := Gear^.State or gstCollision; |
|
333 end; |
395 end; |
334 |
396 |
335 // clip velocity at 2 - over 1 per pixel, but really shouldn't cause many actual problems. |
397 // clip velocity at 2 - over 1 per pixel, but really shouldn't cause many actual problems. |
336 if Gear^.dX.Round > 1 then |
398 if Gear^.dX.Round > 1 then |
337 Gear^.dX.QWordValue:= 8589934592; |
399 Gear^.dX.QWordValue:= 8589934592; |
342 begin |
404 begin |
343 Gear^.dX:= Gear^.dX * _0_999; |
405 Gear^.dX:= Gear^.dX * _0_999; |
344 Gear^.dY:= Gear^.dY * _0_999 |
406 Gear^.dY:= Gear^.dY * _0_999 |
345 end; |
407 end; |
346 |
408 |
347 Gear^.State := Gear^.State and (not gstCollision); |
|
348 collV := 0; |
409 collV := 0; |
349 collH := 0; |
410 collH := 0; |
350 tdX := Gear^.dX; |
411 tdX := Gear^.dX; |
351 tdY := Gear^.dY; |
412 tdY := Gear^.dY; |
352 |
413 |
428 else if Gear^.AdvBounce = 1 then |
489 else if Gear^.AdvBounce = 1 then |
429 begin |
490 begin |
430 xland:= TestCollisionXwithGear(Gear, -hwSign(Gear^.dX)); |
491 xland:= TestCollisionXwithGear(Gear, -hwSign(Gear^.dX)); |
431 if xland <> 0 then collH := -hwSign(Gear^.dX) |
492 if xland <> 0 then collH := -hwSign(Gear^.dX) |
432 end; |
493 end; |
433 //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then |
|
434 if (collV <> 0) and (collH <> 0) and |
494 if (collV <> 0) and (collH <> 0) and |
435 (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then |
495 (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then |
436 //or ((xland or land) and lfBouncy <> 0)) then |
|
437 begin |
496 begin |
438 if (xland or land) and lfBouncy = 0 then |
497 if (xland or land) and lfBouncy = 0 then |
439 begin |
498 begin |
440 Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction; |
499 Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction; |
441 Gear^.dY := tdX*Gear^.Elasticity; |
500 Gear^.dY := tdX*Gear^.Elasticity; |
484 end; |
543 end; |
485 |
544 |
486 Gear^.X := Gear^.X + Gear^.dX; |
545 Gear^.X := Gear^.X + Gear^.dX; |
487 Gear^.Y := Gear^.Y + Gear^.dY; |
546 Gear^.Y := Gear^.Y + Gear^.dY; |
488 CheckGearDrowning(Gear); |
547 CheckGearDrowning(Gear); |
489 //if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _0_0002) and |
|
490 if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then |
548 if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then |
491 Gear^.State := Gear^.State and (not gstMoving) |
549 Gear^.State := Gear^.State and (not gstMoving) |
492 else |
550 else |
493 Gear^.State := Gear^.State or gstMoving; |
551 Gear^.State := Gear^.State or gstMoving; |
494 |
552 |
495 if ((xland or land) and lfBouncy <> 0) and (Gear^.dX.QWordValue < _0_15.QWordValue) and (Gear^.dY.QWordValue < _0_15.QWordValue) then |
553 if ((xland or land) and lfBouncy <> 0) and (Gear^.dX.QWordValue < _0_15.QWordValue) and (Gear^.dY.QWordValue < _0_15.QWordValue) then |
496 Gear^.State := Gear^.State or gstCollision; |
554 Gear^.State := Gear^.State or gstCollision; |
497 |
555 |
498 if ((xland or land) and lfBouncy <> 0) and (Gear^.Radius >= 3) and |
556 if ((xland or land) and lfBouncy <> 0) and |
499 ((Gear^.dX.QWordValue > _0_15.QWordValue) or (Gear^.dY.QWordValue > _0_15.QWordValue)) then |
557 ((Gear^.dX.QWordValue > _0_15.QWordValue) or (Gear^.dY.QWordValue > _0_15.QWordValue)) then |
500 begin |
558 begin |
501 AddBounceEffectForGear(Gear); |
559 AddBounceEffectForGear(Gear); |
502 end |
560 end |
503 else if (Gear^.nImpactSounds > 0) and |
561 else if (Gear^.nImpactSounds > 0) and |
524 if Gear^.Timer = 1000 then // might need adjustments |
582 if Gear^.Timer = 1000 then // might need adjustments |
525 case Gear^.Kind of |
583 case Gear^.Kind of |
526 gtGrenade, |
584 gtGrenade, |
527 gtClusterBomb, |
585 gtClusterBomb, |
528 gtWatermelon, |
586 gtWatermelon, |
529 gtHellishBomb: makeHogsWorry(Gear^.X, Gear^.Y, Gear^.Boom); |
587 gtHellishBomb: makeHogsWorry(Gear^.X, Gear^.Y, Gear^.Boom, Gear^.Kind); |
530 gtGasBomb: makeHogsWorry(Gear^.X, Gear^.Y, 50); |
588 gtGasBomb: makeHogsWorry(Gear^.X, Gear^.Y, 50, Gear^.Kind); |
531 end; |
589 end; |
532 |
590 |
533 if (Gear^.Kind = gtBall) and ((Gear^.State and gstTmpFlag) <> 0) then |
591 if (Gear^.Kind = gtBall) and ((Gear^.State and gstTmpFlag) <> 0) then |
534 begin |
592 begin |
535 CheckCollision(Gear); |
593 CheckCollision(Gear); |
662 PlaySound(sndMolotov); |
720 PlaySound(sndMolotov); |
663 gX := hwRound(Gear^.X); |
721 gX := hwRound(Gear^.X); |
664 gY := hwRound(Gear^.Y); |
722 gY := hwRound(Gear^.Y); |
665 for i:= 0 to 4 do |
723 for i:= 0 to 4 do |
666 begin |
724 begin |
667 (*glass:= AddVisualGear(gx+random(7)-3, gy+random(5)-2, vgtEgg); |
725 glass:= AddVisualGear(gx+random(7)-3, gy+random(7)-3, vgtEgg); |
668 if glass <> nil then |
|
669 begin |
|
670 glass^.Frame:= 2; |
|
671 glass^.Tint:= $41B83ED0 - i * $10081000; |
|
672 glass^.dX:= 1/(10*(random(11)-5)); |
|
673 glass^.dY:= -1/(random(4)+5); |
|
674 end;*) |
|
675 glass:= AddVisualGear(gx+random(7)-3, gy+random(7)-3, vgtStraightShot); |
|
676 if glass <> nil then |
726 if glass <> nil then |
677 with glass^ do |
727 with glass^ do |
678 begin |
728 begin |
679 Frame:= 2; |
729 Frame:= 2; |
680 Tint:= $41B83ED0 - i * $10081000; |
730 Tint:= $41B83ED0 - i * $10081000; |
731 dX:= dX + hwFloat2Float(Gear^.dX) / 2; |
|
681 Angle:= random(360); |
732 Angle:= random(360); |
682 dx:= 0.0000001; |
|
683 dy:= 0; |
|
684 if random(2) = 0 then |
|
685 dx := -dx; |
|
686 FrameTicks:= 750; |
733 FrameTicks:= 750; |
687 State:= ord(sprEgg) |
734 State:= ord(sprEgg) |
688 end; |
735 end; |
689 end; |
736 end; |
690 for i:= 0 to 24 do |
737 for i:= 0 to 24 do |
792 CheckCollision(Gear); |
839 CheckCollision(Gear); |
793 if ((Gear^.State and gstCollision) <> 0) or ((Gear^.State and gstMoving) = 0) then |
840 if ((Gear^.State and gstCollision) <> 0) or ((Gear^.State and gstMoving) = 0) then |
794 draw:= true; |
841 draw:= true; |
795 xx:= hwRound(Gear^.X); |
842 xx:= hwRound(Gear^.X); |
796 yy:= hwRound(Gear^.Y); |
843 yy:= hwRound(Gear^.Y); |
797 if draw and (WorldEdge = weWrap) and ((xx < LongInt(leftX) + 3) or (xx > LongInt(rightX) - 3)) then |
844 if draw and (WorldEdge = weWrap) and ((xx < leftX + 3) or (xx > rightX - 3)) then |
798 begin |
845 begin |
799 if xx < LongInt(leftX) + 3 then |
846 if xx < leftX + 3 then |
800 xx:= rightX-3 |
847 xx:= rightX-3 |
801 else xx:= leftX+3; |
848 else xx:= leftX+3; |
802 Gear^.X:= int2hwFloat(xx) |
849 Gear^.X:= int2hwFloat(xx) |
803 end |
850 end |
804 end |
851 end |
817 if DirAngle < 0 then |
864 if DirAngle < 0 then |
818 DirAngle := DirAngle + 360 |
865 DirAngle := DirAngle + 360 |
819 else if 360 < DirAngle then |
866 else if 360 < DirAngle then |
820 DirAngle := DirAngle - 360; |
867 DirAngle := DirAngle - 360; |
821 end; |
868 end; |
822 (* |
|
823 We aren't using frametick right now, so just a waste of cycles. |
|
824 inc(Health, 8); |
|
825 if longword(Health) > vobFrameTicks then |
|
826 begin |
|
827 dec(Health, vobFrameTicks); |
|
828 inc(Timer); |
|
829 if Timer = vobFramesCount then |
|
830 Timer:= 0 |
|
831 end; |
|
832 *) |
|
833 // move back to cloud layer |
869 // move back to cloud layer |
834 if CheckCoordInWater(xx, yy) then |
870 if CheckCoordInWater(xx, yy) then |
835 move:= true |
871 move:= true |
836 else if (xx > snowRight) or (xx < snowLeft) then |
872 else if (xx > snowRight) or (xx < snowLeft) then |
837 move:=true |
873 move:=true |
996 //////////////////////////////////////////////////////////////////////////////// |
1032 //////////////////////////////////////////////////////////////////////////////// |
997 procedure doStepBeeWork(Gear: PGear); |
1033 procedure doStepBeeWork(Gear: PGear); |
998 var |
1034 var |
999 t: hwFloat; |
1035 t: hwFloat; |
1000 gX,gY,i: LongInt; |
1036 gX,gY,i: LongInt; |
1001 uw, nuw: boolean; |
1037 uw, nuw, wrapped: boolean; |
1002 flower: PVisualGear; |
1038 flower: PVisualGear; |
1003 |
1039 |
1004 begin |
1040 begin |
1005 WorldWrap(Gear); |
1041 wrapped:= WorldWrap(Gear); |
1042 if wrapped then |
|
1043 HomingWrap(Gear); |
|
1044 |
|
1006 AllInactive := false; |
1045 AllInactive := false; |
1007 gX := hwRound(Gear^.X); |
1046 gX := hwRound(Gear^.X); |
1008 gY := hwRound(Gear^.Y); |
1047 gY := hwRound(Gear^.Y); |
1009 uw := (Gear^.Tag <> 0); // was bee underwater last tick? |
1048 uw := (Gear^.Tag <> 0); // was bee underwater last tick? |
1010 nuw := CheckCoordInWater(gx, gy + Gear^.Radius); // is bee underwater now? |
1049 nuw := CheckCoordInWater(gx, gy + Gear^.Radius); // is bee underwater now? |
1028 end; |
1067 end; |
1029 |
1068 |
1030 |
1069 |
1031 if Gear^.Timer = 0 then |
1070 if Gear^.Timer = 0 then |
1032 begin |
1071 begin |
1033 // no "fuel"? just fall |
1072 // no energy? just fall |
1034 doStepFallingGear(Gear); |
1073 doStepFallingGear(Gear); |
1035 // if drowning, stop bee sound |
1074 // if drowning, stop bee sound |
1036 if (Gear^.State and gstDrowning) <> 0 then |
1075 if (Gear^.State and gstDrowning) <> 0 then |
1037 StopSoundChan(Gear^.SoundChannel); |
1076 StopSoundChan(Gear^.SoundChannel); |
1038 end |
1077 end |
1095 end; |
1134 end; |
1096 end; |
1135 end; |
1097 end; |
1136 end; |
1098 |
1137 |
1099 procedure doStepBee(Gear: PGear); |
1138 procedure doStepBee(Gear: PGear); |
1139 var wrapped: boolean; |
|
1100 begin |
1140 begin |
1101 AllInactive := false; |
1141 AllInactive := false; |
1102 Gear^.X := Gear^.X + Gear^.dX; |
1142 Gear^.X := Gear^.X + Gear^.dX; |
1103 Gear^.Y := Gear^.Y + Gear^.dY; |
1143 Gear^.Y := Gear^.Y + Gear^.dY; |
1104 WorldWrap(Gear); |
1144 wrapped:= WorldWrap(Gear); |
1145 if wrapped then |
|
1146 HomingWrap(Gear); |
|
1105 Gear^.dY := Gear^.dY + cGravity; |
1147 Gear^.dY := Gear^.dY + cGravity; |
1106 CheckGearDrowning(Gear); |
1148 CheckGearDrowning(Gear); |
1107 CheckCollision(Gear); |
1149 CheckCollision(Gear); |
1108 if (Gear^.State and gstCollision) <> 0 then |
1150 if (Gear^.State and gstCollision) <> 0 then |
1109 begin |
1151 begin |
1138 DeleteGear(Gear); |
1180 DeleteGear(Gear); |
1139 AfterAttack |
1181 AfterAttack |
1140 end |
1182 end |
1141 end |
1183 end |
1142 else |
1184 else |
1143 begin |
|
1144 DeleteGear(Gear); |
1185 DeleteGear(Gear); |
1145 end |
|
1146 end; |
1186 end; |
1147 |
1187 |
1148 procedure CreateShellForGear(Gear: PGear; startFrame: Longword); |
1188 procedure CreateShellForGear(Gear: PGear; startFrame: Longword); |
1149 var |
1189 var |
1150 shell: PVisualGear; |
1190 shell: PVisualGear; |
1158 shell^.dY := gear^.dY.QWordValue / -17179869184; |
1198 shell^.dY := gear^.dY.QWordValue / -17179869184; |
1159 shell^.Frame := startFrame; |
1199 shell^.Frame := startFrame; |
1160 end; |
1200 end; |
1161 end; |
1201 end; |
1162 |
1202 |
1203 function ShotgunLineHitHelp(Gear: PGear; oX, oY, tX, tY: hwFloat): Boolean; |
|
1204 var i: LongInt; |
|
1205 Collisions: PGearArray; |
|
1206 begin |
|
1207 ShotgunLineHitHelp := false; |
|
1208 Collisions := CheckAllGearsLineCollision(Gear, oX, oY, tX, tY); |
|
1209 i := Collisions^.Count; |
|
1210 while i > 0 do |
|
1211 begin |
|
1212 dec(i); |
|
1213 if Collisions^.ar[i]^.Kind in |
|
1214 [gtMine, gtSMine, gtAirMine, gtKnife, gtCase, gtTarget, gtExplosives] then |
|
1215 begin |
|
1216 Gear^.X := Collisions^.ar[i]^.X; |
|
1217 Gear^.Y := Collisions^.ar[i]^.Y; |
|
1218 ShotgunShot(Gear); |
|
1219 Gear^.doStep := @doStepShotIdle; |
|
1220 ShotgunLineHitHelp := true; |
|
1221 exit; |
|
1222 end; |
|
1223 end; |
|
1224 end; |
|
1225 |
|
1163 procedure doStepShotgunShot(Gear: PGear); |
1226 procedure doStepShotgunShot(Gear: PGear); |
1164 var |
1227 var |
1165 i: LongWord; |
1228 i: LongWord; |
1229 oX, oY, tmpX, tmpY: hwFloat; |
|
1166 begin |
1230 begin |
1167 AllInactive := false; |
1231 AllInactive := false; |
1168 |
1232 |
1169 if ((Gear^.State and gstAnimation) = 0) then |
1233 if ((Gear^.State and gstAnimation) = 0) then |
1170 begin |
1234 begin |
1184 exit |
1248 exit |
1185 end |
1249 end |
1186 else |
1250 else |
1187 inc(Gear^.Timer); |
1251 inc(Gear^.Timer); |
1188 |
1252 |
1189 i := 200; |
1253 i := 100; |
1254 oX := Gear^.X; |
|
1255 oY := Gear^.Y; |
|
1190 repeat |
1256 repeat |
1191 Gear^.X := Gear^.X + Gear^.dX; |
1257 if Gear^.Tag = 0 then |
1192 Gear^.Y := Gear^.Y + Gear^.dY; |
1258 begin |
1193 WorldWrap(Gear); |
1259 Gear^.X := Gear^.X + Gear^.dX; |
1260 Gear^.Y := Gear^.Y + Gear^.dY; |
|
1261 end; |
|
1262 |
|
1263 tmpX := Gear^.X; |
|
1264 tmpY := Gear^.Y; |
|
1265 if (Gear^.PortalCounter < 30) and WorldWrap(Gear) then |
|
1266 begin |
|
1267 inc(Gear^.PortalCounter); |
|
1268 if ShotgunLineHitHelp(Gear, oX, oY, tmpX, tmpY) then |
|
1269 exit; |
|
1270 oX := Gear^.X; |
|
1271 oY := Gear^.Y; |
|
1272 end; |
|
1194 CheckCollision(Gear); |
1273 CheckCollision(Gear); |
1195 if (Gear^.State and gstCollision) <> 0 then |
1274 |
1196 begin |
1275 if ((Gear^.State and gstCollision) <> 0) then |
1197 Gear^.X := Gear^.X + Gear^.dX * 8; |
1276 begin |
1198 Gear^.Y := Gear^.Y + Gear^.dY * 8; |
1277 if Gear^.Tag = 0 then |
1199 ShotgunShot(Gear); |
1278 begin |
1200 Gear^.doStep := @doStepShotIdle; |
1279 //Try to align the shot with the land to give portals a chance to catch it |
1201 exit |
1280 Gear^.X := Gear^.X + Gear^.dX * 2; |
1202 end; |
1281 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1282 Gear^.Tag := 1 |
|
1283 end |
|
1284 else |
|
1285 begin |
|
1286 Gear^.X := Gear^.X + Gear^.dX * 6; |
|
1287 Gear^.Y := Gear^.Y + Gear^.dY * 6; |
|
1288 ShotgunShot(Gear); |
|
1289 Gear^.doStep := @doStepShotIdle; |
|
1290 end; |
|
1291 exit |
|
1292 end |
|
1293 else |
|
1294 Gear^.Tag := 0; |
|
1203 |
1295 |
1204 CheckGearDrowning(Gear); |
1296 CheckGearDrowning(Gear); |
1205 if (Gear^.State and gstDrowning) <> 0 then |
1297 if (Gear^.State and gstDrowning) <> 0 then |
1206 begin |
1298 begin |
1207 Gear^.doStep := @doStepShotIdle; |
1299 Gear^.doStep := @doStepShotIdle; |
1208 exit |
1300 break; |
1209 end; |
1301 end; |
1210 dec(i) |
1302 dec(i) |
1211 until i = 0; |
1303 until i = 0; |
1304 |
|
1305 ShotgunLineHitHelp(Gear, oX, oY, Gear^.X, Gear^.Y); |
|
1306 |
|
1212 if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then |
1307 if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then |
1213 Gear^.doStep := @doStepShotIdle |
1308 Gear^.doStep := @doStepShotIdle |
1214 end; |
1309 end; |
1215 |
1310 |
1216 //////////////////////////////////////////////////////////////////////////////// |
1311 //////////////////////////////////////////////////////////////////////////////// |
1299 end; |
1394 end; |
1300 |
1395 |
1301 procedure LineShoveHelp(Gear: PGear; oX, oY, tX, tY, dX, dY: hwFloat; count: LongWord); |
1396 procedure LineShoveHelp(Gear: PGear; oX, oY, tX, tY, dX, dY: hwFloat; count: LongWord); |
1302 var dmg,power: LongInt; |
1397 var dmg,power: LongInt; |
1303 begin |
1398 begin |
1304 if ((Gear^.Kind = gtMinigunBullet) or (Gear^.Damage > 0)) |
1399 if hwSqr(tX - oX) + hwSqr(tY - oY) > _0_25 then |
1305 and (hwSqr(tX - oX) + hwSqr(tY - oY) > _0_25) then |
|
1306 begin |
1400 begin |
1307 if (Gear^.AmmoType = amDEagle) or (Gear^.AmmoType = amMinigun) then |
1401 if (Gear^.AmmoType = amDEagle) or (Gear^.AmmoType = amMinigun) then |
1308 dmg:= Gear^.Boom |
1402 dmg:= Gear^.Boom |
1309 else |
1403 else |
1310 dmg:= Gear^.Timer * Gear^.Boom div 100000; |
1404 dmg:= Gear^.Timer * Gear^.Boom div 100000; |
1320 dec(Gear^.Health, Gear^.Damage); |
1414 dec(Gear^.Health, Gear^.Damage); |
1321 Gear^.Damage := 0 |
1415 Gear^.Damage := 0 |
1322 end; |
1416 end; |
1323 end; |
1417 end; |
1324 |
1418 |
1419 procedure CheckBulletDrowningHelp(Bullet: PGear); |
|
1420 var dX, dY: hwFloat; |
|
1421 begin |
|
1422 dX := Bullet^.dX; |
|
1423 dY := Bullet^.dY; |
|
1424 CheckGearDrowning(Bullet); |
|
1425 if (dX <> Bullet^.dX) or (dY <> Bullet^.dY) then |
|
1426 begin |
|
1427 SpawnBulletTrail(Bullet, Bullet^.X, Bullet^.Y, Bullet^.FlightTime = 0); |
|
1428 Bullet^.Elasticity := Bullet^.X; |
|
1429 Bullet^.Friction := Bullet^.Y; |
|
1430 Inc(Bullet^.PortalCounter); |
|
1431 Bullet^.FlightTime:= 1; |
|
1432 end; |
|
1433 end; |
|
1434 |
|
1435 procedure CreateBubblesForBullet(Gear: PGear); |
|
1436 var i, iInit: LongWord; |
|
1437 begin |
|
1438 iInit:= 0; |
|
1439 if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Health > 0) then |
|
1440 begin |
|
1441 // draw bubbles |
|
1442 if (not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF)) then |
|
1443 begin |
|
1444 case Gear^.Kind of |
|
1445 gtMinigunBullet: iInit:= Gear^.Health * 100; |
|
1446 gtDEagleShot, gtSniperRifleShot: iInit:= Gear^.Health * 4 |
|
1447 end; |
|
1448 for i:=iInit downto 0 do |
|
1449 begin |
|
1450 if Random(6) = 0 then |
|
1451 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); |
|
1452 Gear^.X := Gear^.X + Gear^.dX; |
|
1453 Gear^.Y := Gear^.Y + Gear^.dY; |
|
1454 end; |
|
1455 end; |
|
1456 // bullet dies underwater |
|
1457 Gear^.Health:= 0; |
|
1458 end; |
|
1459 end; |
|
1460 |
|
1325 procedure doStepBulletWork(Gear: PGear); |
1461 procedure doStepBulletWork(Gear: PGear); |
1326 var |
1462 var |
1327 i, x, y, iInit: LongWord; |
1463 i, x, y, iInit: LongWord; |
1328 oX, oY, tX, tY, tDx, tDy: hwFloat; |
1464 oX, oY, tX, tY, tDx, tDy: hwFloat; |
1329 VGear: PVisualGear; |
1465 VGear: PVisualGear; |
1376 begin |
1512 begin |
1377 Gear^.Tag := 1; |
1513 Gear^.Tag := 1; |
1378 dec(Gear^.Damage); |
1514 dec(Gear^.Damage); |
1379 Gear^.X := Gear^.X - Gear^.dX; |
1515 Gear^.X := Gear^.X - Gear^.dX; |
1380 Gear^.Y := Gear^.Y - Gear^.dY; |
1516 Gear^.Y := Gear^.Y - Gear^.dY; |
1381 CheckGearDrowning(Gear); |
1517 CheckBulletDrowningHelp(Gear); |
1382 break; |
1518 break; |
1383 end |
1519 end |
1384 else if (not isDigging) then |
1520 else if (not isDigging) then |
1385 Gear^.Tag := 0; |
1521 Gear^.Tag := 0; |
1386 |
1522 |
1393 iInit:= i; |
1529 iInit:= i; |
1394 oX:= Gear^.X; |
1530 oX:= Gear^.X; |
1395 oY:= Gear^.Y; |
1531 oY:= Gear^.Y; |
1396 end; |
1532 end; |
1397 |
1533 |
1398 CheckGearDrowning(Gear); |
1534 CheckBulletDrowningHelp(Gear); |
1399 case Gear^.Kind of |
1535 case Gear^.Kind of |
1400 gtMinigunBullet: isDead:= isDigging; |
1536 gtMinigunBullet: isDead:= isDigging or ((Gear^.State and gstDrowning) <> 0); |
1401 gtDEagleShot, gtSniperRifleShot: isDead:= Gear^.Damage >= Gear^.Health; |
1537 gtDEagleShot, gtSniperRifleShot: isDead:= (Gear^.Damage >= Gear^.Health) or ((Gear^.State and gstDrowning) <> 0) |
1402 end; |
1538 end; |
1403 dec(i) |
1539 dec(i) |
1404 until (i = 0) or (isDead) or ((Gear^.State and gstDrowning) <> 0); |
1540 until (i = 0) or (isDead); |
1405 |
1541 |
1406 LineShoveHelp(Gear, oX, oY, Gear^.X, Gear^.Y, |
1542 LineShoveHelp(Gear, oX, oY, Gear^.X, Gear^.Y, |
1407 Gear^.dX, Gear^.dY, iInit + 2 - i); |
1543 Gear^.dX, Gear^.dY, iInit + 2 - i); |
1408 |
1544 |
1409 if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Health > 0) then |
1545 CreateBubblesForBullet(Gear); |
1410 begin |
1546 |
1411 // draw bubbles |
1547 x := hwRound(Gear^.X); |
1412 if (not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF)) then |
1548 y := hwRound(Gear^.Y); |
1413 begin |
1549 if (isDead) or (x and LAND_WIDTH_MASK <> 0) or (y and LAND_HEIGHT_MASK <> 0) then |
1414 for i:=(Gear^.Health * 4) downto 0 do |
1550 begin |
1415 begin |
1551 if (Gear^.Kind = gtSniperRifleShot) then |
1416 if Random(6) = 0 then |
1552 cLaserSightingSniper := false; |
1417 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble); |
1553 if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and (CurrentHedgehog^.Effects[heArtillery] = 2) then |
1418 Gear^.X := Gear^.X + Gear^.dX; |
1554 CurrentHedgehog^.Effects[heArtillery]:= 0; |
1419 Gear^.Y := Gear^.Y + Gear^.dY; |
1555 |
1556 // Bullet Hit |
|
1557 if ((Gear^.State and gstDrowning) = 0) and (x and LAND_WIDTH_MASK = 0) and (y and LAND_HEIGHT_MASK = 0) then |
|
1558 begin |
|
1559 if Gear^.Kind = gtMinigunBullet then |
|
1560 begin |
|
1561 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 5, |
|
1562 Gear^.Hedgehog, (EXPLNoDamage or EXPLDoNotTouchHH){ or EXPLDontDraw or EXPLNoGfx}); |
|
1563 VGear := AddVisualGear(hwRound(Gear^.X + Gear^.dX * 5), hwRound(Gear^.Y + Gear^.dY * 5), vgtBulletHit); |
|
1564 end |
|
1565 else |
|
1566 VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit); |
|
1567 |
|
1568 if VGear <> nil then |
|
1569 begin |
|
1570 VGear^.Angle := DxDy2Angle(-Gear^.dX, Gear^.dY); |
|
1420 end; |
1571 end; |
1421 end; |
1572 end; |
1422 // bullet dies underwater |
1573 |
1423 Gear^.Health:= 0; |
1574 spawnBulletTrail(Gear, Gear^.X, Gear^.Y, Gear^.FlightTime = 0); |
1424 end; |
1575 Gear^.FlightTime:= 1; |
1425 |
1576 if Gear^.Kind = gtMinigunBullet then |
1426 if (isDead) |
1577 ClearHitOrderLeq(Gear^.Tag); |
1427 or (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) |
1578 |
1428 or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then |
1579 if (worldEdge = weSea) and (Gear^.Kind = gtMinigunBullet) |
1429 begin |
1580 and Gear^.Y.isNegative and Gear^.dY.isNegative |
1430 if (Gear^.Kind = gtSniperRifleShot) then |
1581 and (Gear^.Health > 0) and (not isZero(Gear^.dX)) then |
1431 cLaserSightingSniper := false; |
1582 begin |
1432 if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and (CurrentHedgehog^.Effects[heArtillery] = 2) then |
1583 if Gear^.dX.isNegative then |
1433 CurrentHedgehog^.Effects[heArtillery]:= 0; |
1584 begin |
1434 |
1585 |
1435 // Bullet Hit |
1586 Gear^.X:= int2hwFloat(-1); |
1436 if ((Gear^.State and gstDrowning) = 0) and (hwRound(Gear^.X) and LAND_WIDTH_MASK = 0) and (hwRound(Gear^.Y) and LAND_HEIGHT_MASK = 0) then |
1587 iInit:= x - leftX; |
1437 begin |
1588 end |
1438 if Gear^.Kind = gtMinigunBullet then |
1589 else |
1439 begin |
1590 begin |
1440 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 5, |
1591 Gear^.X:= int2hwFloat(LAND_WIDTH); |
1441 Gear^.Hedgehog, EXPLNoDamage{ or EXPLDontDraw or EXPLNoGfx}); |
1592 iInit:= rightX - x - 1; |
1442 VGear := AddVisualGear(hwRound(Gear^.X + Gear^.dX * 5), hwRound(Gear^.Y + Gear^.dY * 5), vgtBulletHit); |
|
1443 end |
|
1444 else |
|
1445 VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit); |
|
1446 |
|
1447 if VGear <> nil then |
|
1448 begin |
|
1449 VGear^.Angle := DxDy2Angle(-Gear^.dX, Gear^.dY); |
|
1450 end; |
|
1451 end; |
1593 end; |
1452 |
1594 Gear^.Y:= Gear^.Y + Gear^.dY * hwAbs(int2hwFloat(iInit) / Gear^.dX); |
1453 spawnBulletTrail(Gear, Gear^.X, Gear^.Y, Gear^.FlightTime = 0); |
1595 CheckGearDrowning(Gear); |
1454 Gear^.FlightTime:= 1; |
1596 CreateBubblesForBullet(Gear); |
1455 if Gear^.Kind = gtMinigunBullet then |
1597 end; |
1456 ClearHitOrderLeq(Gear^.Tag); |
1598 Gear^.doStep := @doStepShotIdle |
1457 Gear^.doStep := @doStepShotIdle |
1599 end; |
1458 end; |
|
1459 end; |
1600 end; |
1460 |
1601 |
1461 procedure doStepDEagleShot(Gear: PGear); |
1602 procedure doStepDEagleShot(Gear: PGear); |
1462 begin |
1603 begin |
1463 Gear^.Data:= nil; |
1604 Gear^.Data:= nil; |
1464 // remember who fired this |
1605 // remember who fired this |
1465 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
1606 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
1466 Gear^.Data:= Pointer(Gear^.Hedgehog^.Gear); |
1607 Gear^.Data:= Pointer(Gear^.Hedgehog^.Gear); |
1467 |
1608 |
1468 PlaySound(sndGun); |
1609 PlaySound(sndGun); |
1610 ClearHitOrder(); |
|
1469 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just plain old weird angles |
1611 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just plain old weird angles |
1470 Gear^.X := Gear^.X + Gear^.dX * 2; |
1612 Gear^.X := Gear^.X + Gear^.dX * 2; |
1471 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1613 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1472 Gear^.FlightTime := 0; |
1614 Gear^.FlightTime := 0; |
1473 Gear^.doStep := @doStepBulletWork |
1615 Gear^.doStep := @doStepBulletWork |
1506 CreateShellForGear(Gear, 1); |
1648 CreateShellForGear(Gear, 1); |
1507 Gear^.State := Gear^.State or gstAnimation; |
1649 Gear^.State := Gear^.State or gstAnimation; |
1508 Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5; |
1650 Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5; |
1509 Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5; |
1651 Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5; |
1510 PlaySound(sndGun); |
1652 PlaySound(sndGun); |
1653 ClearHitOrder(); |
|
1511 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just weird angles |
1654 // add 2 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just weird angles |
1512 Gear^.X := Gear^.X + Gear^.dX * 2; |
1655 Gear^.X := Gear^.X + Gear^.dX * 2; |
1513 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1656 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
1514 Gear^.FlightTime := 0; |
1657 Gear^.FlightTime := 0; |
1515 Gear^.doStep := @doStepBulletWork; |
1658 Gear^.doStep := @doStepBulletWork; |
1541 gtATStartGame: |
1684 gtATStartGame: |
1542 begin |
1685 begin |
1543 AllInactive := false; |
1686 AllInactive := false; |
1544 if Gear^.Timer = 0 then |
1687 if Gear^.Timer = 0 then |
1545 begin |
1688 begin |
1546 AddCaption(GetEventString(eidRoundStart), cWhiteColor, capgrpGameState); |
1689 AddCaption(GetEventString(eidRoundStart), capcolDefault, capgrpGameState); |
1547 end |
1690 end |
1548 end; |
1691 end; |
1549 gtATFinishGame: |
1692 gtATFinishGame: |
1550 begin |
1693 begin |
1551 AllInactive := false; |
1694 AllInactive := false; |
1556 ScreenFadeSpeed := 1; |
1699 ScreenFadeSpeed := 1; |
1557 end; |
1700 end; |
1558 if Gear^.Timer = 0 then |
1701 if Gear^.Timer = 0 then |
1559 begin |
1702 begin |
1560 SendIPC(_S'N'); |
1703 SendIPC(_S'N'); |
1704 if (luaCmdUsed) then |
|
1705 SendIPC(_S'm'); |
|
1561 SendIPC(_S'q'); |
1706 SendIPC(_S'q'); |
1562 GameState := gsExit |
1707 GameState := gsExit |
1563 end |
1708 end |
1564 end; |
1709 end; |
1565 end; |
1710 end; |
1606 |
1751 |
1607 i := x - Gear^.Radius - LongInt(GetRandom(2)); |
1752 i := x - Gear^.Radius - LongInt(GetRandom(2)); |
1608 ei := x + Gear^.Radius + LongInt(GetRandom(2)); |
1753 ei := x + Gear^.Radius + LongInt(GetRandom(2)); |
1609 while i <= ei do |
1754 while i <= ei do |
1610 begin |
1755 begin |
1611 DrawExplosion(i, y + 3, 3); |
1756 doMakeExplosion(i, y + 3, 3, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx or EXPLForceDraw); |
1612 inc(i, 1) |
1757 inc(i, 1) |
1613 end; |
1758 end; |
1614 |
1759 |
1615 if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9), lfIndestructible) then |
1760 if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9), lfIndestructible) then |
1616 begin |
1761 begin |
1819 var vg: PVisualGear; |
1964 var vg: PVisualGear; |
1820 dxdy: hwFloat; |
1965 dxdy: hwFloat; |
1821 dmg: LongWord; |
1966 dmg: LongWord; |
1822 begin |
1967 begin |
1823 if Gear^.Health = 0 then dxdy:= hwAbs(Gear^.dX)+hwAbs(Gear^.dY); |
1968 if Gear^.Health = 0 then dxdy:= hwAbs(Gear^.dX)+hwAbs(Gear^.dY); |
1969 Gear^.RenderTimer:= ((Gear^.State and gstFrozen) = 0) and ((Gear^.State and gstAttacking) = 0) and (Gear^.Health <> 0); |
|
1824 if (Gear^.State and gstMoving) <> 0 then |
1970 if (Gear^.State and gstMoving) <> 0 then |
1825 begin |
1971 begin |
1826 DeleteCI(Gear); |
1972 DeleteCI(Gear); |
1827 doStepFallingGear(Gear); |
1973 doStepFallingGear(Gear); |
1828 if (Gear^.State and gstMoving) = 0 then |
1974 if (Gear^.State and gstMoving) = 0 then |
1885 if ((Gear^.State and gstWait) <> 0) |
2031 if ((Gear^.State and gstWait) <> 0) |
1886 or (cMineDudPercent = 0) |
2032 or (cMineDudPercent = 0) |
1887 or (getRandom(100) > cMineDudPercent) then |
2033 or (getRandom(100) > cMineDudPercent) then |
1888 begin |
2034 begin |
1889 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
2035 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
1890 DeleteGear(Gear) |
2036 DeleteGear(Gear); |
2037 exit // redundant but we've had too many delete gear bugs |
|
1891 end |
2038 end |
1892 else |
2039 else |
1893 begin |
2040 begin |
1894 vg:= AddVisualGear(hwRound(Gear^.X) - 4 + Random(8), hwRound(Gear^.Y) - 4 - Random(4), vgtSmoke); |
2041 vg:= AddVisualGear(hwRound(Gear^.X) - 4 + Random(8), hwRound(Gear^.Y) - 4 - Random(4), vgtSmoke); |
1895 if vg <> nil then |
2042 if vg <> nil then |
1913 procedure doStepAirMine(Gear: PGear); |
2060 procedure doStepAirMine(Gear: PGear); |
1914 var i,t,targDist,tmpDist: LongWord; |
2061 var i,t,targDist,tmpDist: LongWord; |
1915 targ, tmpG: PGear; |
2062 targ, tmpG: PGear; |
1916 trackSpeed, airFriction, tX, tY: hwFloat; |
2063 trackSpeed, airFriction, tX, tY: hwFloat; |
1917 isUnderwater: Boolean; |
2064 isUnderwater: Boolean; |
1918 begin |
2065 sparkle: PVisualGear; |
2066 begin |
|
2067 targ:= nil; |
|
2068 Gear^.RenderTimer:= ((Gear^.State and gstFrozen) = 0) and ((Gear^.State and gstAttacking) = 0); |
|
2069 if (Gear^.State and gstFrozen) <> 0 then |
|
2070 begin |
|
2071 if Gear^.Damage > 0 then |
|
2072 begin |
|
2073 // Normal, damaging explosion |
|
2074 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
2075 if ((Gear^.State and gstNoGravity) <> 0) then |
|
2076 // Remove land created by frozen air mine sprite pixel-perfectly |
|
2077 EraseLand( |
|
2078 hwRound(Gear^.X) - SpritesData[sprFrozenAirMine].Width div 2, |
|
2079 hwRound(Gear^.Y) - SpritesData[sprFrozenAirMine].Height div 2, |
|
2080 sprFrozenAirMine, 0, 0, false, false, false, false); |
|
2081 DeleteGear(Gear); |
|
2082 exit |
|
2083 end; |
|
2084 if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) or ((GameTicks and $3F) = 15) then |
|
2085 doStepFallingGear(Gear); |
|
2086 exit |
|
2087 end; |
|
1919 isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); |
2088 isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); |
1920 if Gear^.Pos > 0 then |
2089 if Gear^.Pos > 0 then |
1921 begin |
2090 begin |
1922 airFriction:= _1; |
2091 airFriction:= _1; |
1923 if isUnderwater then |
2092 if isUnderwater then |
1925 else |
2094 else |
1926 dec(airFriction.QWordValue,Gear^.Pos); |
2095 dec(airFriction.QWordValue,Gear^.Pos); |
1927 Gear^.dX:= Gear^.dX*airFriction; |
2096 Gear^.dX:= Gear^.dX*airFriction; |
1928 Gear^.dY:= Gear^.dY*airFriction |
2097 Gear^.dY:= Gear^.dY*airFriction |
1929 end; |
2098 end; |
1930 doStepFallingGear(Gear); |
2099 if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) or ((GameTicks and $3F) = 15) then |
2100 doStepFallingGear(Gear); |
|
1931 if (TurnTimeLeft = 0) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then |
2101 if (TurnTimeLeft = 0) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then |
1932 AllInactive := false; |
2102 AllInactive := false; |
2103 |
|
2104 // Disable targeting if airmine is not active yet |
|
2105 if ((Gear^.State and gsttmpFlag) = 0) then |
|
2106 begin |
|
2107 if (TurnTimeLeft = 0) |
|
2108 or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) |
|
2109 or (CurrentHedgehog^.Gear = nil) then |
|
2110 begin |
|
2111 Gear^.FlightTime:= GameTicks; |
|
2112 Gear^.State := Gear^.State or gsttmpFlag; |
|
2113 Gear^.Hedgehog := nil; |
|
2114 end; |
|
2115 exit; |
|
2116 end; |
|
2117 |
|
2118 //Disable targeting while the airmine is stunned |
|
2119 if Gear^.Tag <> 0 then |
|
2120 begin |
|
2121 if ((Gear^.FlightTime and $FF) = 0) then |
|
2122 // spawn lots of particles when stunned (sparkles or bubbles) |
|
2123 if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) = false then |
|
2124 begin |
|
2125 sparkle:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust, 1); |
|
2126 if sparkle <> nil then |
|
2127 begin |
|
2128 sparkle^.dX:= 0.004 * (random(100) - 50); |
|
2129 sparkle^.dY:= -0.05 + 0.004 * (random(100) - 50); |
|
2130 sparkle^.Tint:= $D5CD8CFF; |
|
2131 sparkle^.Angle:= random(360); |
|
2132 end; |
|
2133 end |
|
2134 else |
|
2135 AddVisualGear(hwRound(Gear^.X) - 8 + random(16), hwRound(Gear^.Y) + 16 + random(8), vgtBubble); |
|
2136 |
|
2137 dec(Gear^.FlightTime); |
|
2138 if Gear^.FlightTime = 0 then |
|
2139 begin |
|
2140 Gear^.Tag:= 0; |
|
2141 Gear^.Hedgehog:= nil; |
|
2142 Gear^.State:= Gear^.State and (not gstAttacking); |
|
2143 Gear^.Timer:= Gear^.WDTimer |
|
2144 end; |
|
2145 exit |
|
2146 end; |
|
1933 |
2147 |
1934 if (TurnTimeLeft = 0) or (Gear^.Angle = 0) or (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.Gear = nil) then |
2148 if (TurnTimeLeft = 0) or (Gear^.Angle = 0) or (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.Gear = nil) then |
1935 begin |
2149 begin |
1936 Gear^.Hedgehog:= nil; |
2150 Gear^.Hedgehog:= nil; |
1937 targ:= nil; |
2151 targ:= nil; |
1941 if targ <> nil then |
2155 if targ <> nil then |
1942 begin |
2156 begin |
1943 tX:=Gear^.X-targ^.X; |
2157 tX:=Gear^.X-targ^.X; |
1944 tY:=Gear^.Y-targ^.Y; |
2158 tY:=Gear^.Y-targ^.Y; |
1945 // allow escaping - should maybe flag this too |
2159 // allow escaping - should maybe flag this too |
1946 if (GameTicks > Gear^.FlightTime+10000) or |
2160 if (GameTicks > Gear^.FlightTime + 10000) or |
1947 ((tX.Round+tY.Round > Gear^.Angle*6) and |
2161 (not ((tX.Round + tY.Round < Gear^.Angle * 9) and |
1948 (hwRound(hwSqr(tX) + hwSqr(tY)) > sqr(Gear^.Angle*6))) then |
2162 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Angle * 6)))) |
2163 then |
|
1949 targ:= nil |
2164 targ:= nil |
1950 end; |
2165 end; |
1951 |
2166 |
1952 // If in ready timer, or after turn, or in first 5 seconds of turn (really a window due to extra time utility) |
2167 // If in ready timer, or after turn, or in first 5 seconds of turn (really a window due to extra time utility) |
1953 // or mine is inactive due to lack of gsttmpflag or hunting is disabled due to seek radius of 0 |
2168 // or hunting is disabled due to seek radius of 0 then we aren't hunting |
1954 // then we aren't hunting |
|
1955 if (ReadyTimeLeft > 0) or (TurnTimeLeft = 0) or |
2169 if (ReadyTimeLeft > 0) or (TurnTimeLeft = 0) or |
1956 ((TurnTimeLeft < cHedgehogTurnTime) and (cHedgehogTurnTime-TurnTimeLeft < 5000)) or |
2170 ((TurnTimeLeft < cHedgehogTurnTime) and (cHedgehogTurnTime-TurnTimeLeft < 5000)) or |
1957 (Gear^.State and gsttmpFlag = 0) or |
|
1958 (Gear^.Angle = 0) then |
2171 (Gear^.Angle = 0) then |
1959 gear^.State:= gear^.State and (not gstChooseTarget) |
2172 gear^.State:= gear^.State and (not gstChooseTarget) |
1960 else if |
2173 else if |
1961 // todo, allow not finding new target, set timeout on target retention |
2174 // todo, allow not finding new target, set timeout on target retention |
1962 (Gear^.State and gstAttacking = 0) and |
2175 (Gear^.State and gstAttacking = 0) and |
1968 targDist:= Distance(Gear^.X-targ^.X,Gear^.Y-targ^.Y).Round |
2181 targDist:= Distance(Gear^.X-targ^.X,Gear^.Y-targ^.Y).Round |
1969 else targDist:= 0; |
2182 else targDist:= 0; |
1970 for t:= 0 to Pred(TeamsCount) do |
2183 for t:= 0 to Pred(TeamsCount) do |
1971 with TeamsArray[t]^ do |
2184 with TeamsArray[t]^ do |
1972 for i:= 0 to cMaxHHIndex do |
2185 for i:= 0 to cMaxHHIndex do |
1973 if Hedgehogs[i].Gear <> nil then |
2186 if (Hedgehogs[i].Gear <> nil) and (Hedgehogs[i].Effects[heFrozen] = 0) then |
1974 begin |
2187 begin |
1975 tmpG:= Hedgehogs[i].Gear; |
2188 tmpG:= Hedgehogs[i].Gear; |
1976 tX:=Gear^.X-tmpG^.X; |
2189 tX:=Gear^.X-tmpG^.X; |
1977 tY:=Gear^.Y-tmpG^.Y; |
2190 tY:=Gear^.Y-tmpG^.Y; |
1978 if (Gear^.Angle = $FFFFFFFF) or |
2191 if (Gear^.Angle = $FFFFFFFF) or |
2013 else if (Gear^.Y > targ^.Y) and (Gear^.dY > -_0_1) then |
2226 else if (Gear^.Y > targ^.Y) and (Gear^.dY > -_0_1) then |
2014 Gear^.dY:= Gear^.dY-trackSpeed |
2227 Gear^.dY:= Gear^.dY-trackSpeed |
2015 end |
2228 end |
2016 else Gear^.Hedgehog:= nil; |
2229 else Gear^.Hedgehog:= nil; |
2017 |
2230 |
2018 if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then |
2231 if ((Gear^.State and gstAttacking) = 0) then |
2019 begin |
2232 begin |
2020 if ((Gear^.State and gstAttacking) = 0) then |
2233 if (((GameTicks+Gear^.Uid) and $1F) = 0) then |
2021 begin |
2234 begin |
2022 if ((GameTicks and $1F) = 0) then |
2235 if targ <> nil then |
2023 begin |
2236 begin |
2024 if targ <> nil then |
2237 tX:=Gear^.X-targ^.X; |
2025 begin |
2238 tY:=Gear^.Y-targ^.Y; |
2026 tX:=Gear^.X-targ^.X; |
2239 if (tX.Round+tY.Round < Gear^.Boom) and |
2027 tY:=Gear^.Y-targ^.Y; |
2240 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then |
2028 if (tX.Round+tY.Round < Gear^.Karma) and |
2241 Gear^.State := Gear^.State or gstAttacking |
2029 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Karma)) then |
|
2030 Gear^.State := Gear^.State or gstAttacking |
|
2031 end |
|
2032 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Karma, Gear^.Karma) <> nil) then |
|
2033 Gear^.State := Gear^.State or gstAttacking |
|
2034 end |
2242 end |
2243 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then |
|
2244 Gear^.State := Gear^.State or gstAttacking |
|
2035 end |
2245 end |
2036 else // gstAttacking <> 0 |
2246 end |
2037 begin |
2247 else // gstAttacking <> 0 |
2038 AllInactive := false; |
2248 begin |
2039 if (Gear^.Timer and $FF) = 0 then |
2249 AllInactive := false; |
2040 PlaySound(sndMineTick); |
2250 if (Gear^.Timer and $FF) = 0 then |
2041 if Gear^.Timer = 0 then |
2251 PlaySound(sndMineTick); |
2042 begin |
2252 if Gear^.Timer = 0 then |
2043 // recheck |
2253 begin |
2044 if targ <> nil then |
2254 // recheck |
2045 begin |
2255 if targ <> nil then |
2046 tX:=Gear^.X-targ^.X; |
2256 begin |
2047 tY:=Gear^.Y-targ^.Y; |
2257 tX:=Gear^.X-targ^.X; |
2048 if (tX.Round+tY.Round < Gear^.Karma) and |
2258 tY:=Gear^.Y-targ^.Y; |
2049 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Karma)) then |
2259 if (tX.Round+tY.Round < Gear^.Boom) and |
2050 begin |
2260 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then |
2051 Gear^.Hedgehog:= CurrentHedgehog; |
|
2052 tmpG:= FollowGear; |
|
2053 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Karma, Gear^.Hedgehog, EXPLAutoSound); |
|
2054 FollowGear:= tmpG; |
|
2055 DeleteGear(Gear); |
|
2056 exit |
|
2057 end |
|
2058 end |
|
2059 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Karma, Gear^.Karma) <> nil) then |
|
2060 begin |
2261 begin |
2061 Gear^.Hedgehog:= CurrentHedgehog; |
2262 Gear^.Hedgehog:= CurrentHedgehog; |
2062 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Karma, Gear^.Hedgehog, EXPLAutoSound); |
2263 tmpG:= FollowGear; |
2264 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
2265 FollowGear:= tmpG; |
|
2063 DeleteGear(Gear); |
2266 DeleteGear(Gear); |
2064 exit |
2267 exit |
2065 end; |
2268 end |
2066 Gear^.State:= Gear^.State and (not gstAttacking); |
2269 end |
2067 Gear^.Timer:= Gear^.WDTimer |
2270 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then |
2271 begin |
|
2272 Gear^.Hedgehog:= CurrentHedgehog; |
|
2273 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
2274 DeleteGear(Gear); |
|
2275 exit |
|
2068 end; |
2276 end; |
2069 if Gear^.Timer > 0 then |
2277 Gear^.State:= Gear^.State and (not gstAttacking); |
2070 dec(Gear^.Timer); |
2278 Gear^.Timer:= Gear^.WDTimer |
2071 end |
2279 end; |
2072 end |
2280 if Gear^.Timer > 0 then |
2073 else // gsttmpFlag = 0 |
2281 dec(Gear^.Timer); |
2074 if (TurnTimeLeft = 0) |
|
2075 or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) |
|
2076 or (CurrentHedgehog^.Gear = nil) then |
|
2077 begin |
|
2078 Gear^.FlightTime:= GameTicks; |
|
2079 Gear^.State := Gear^.State or gsttmpFlag |
|
2080 end |
2282 end |
2081 end; |
2283 end; |
2082 |
2284 |
2083 //////////////////////////////////////////////////////////////////////////////// |
2285 //////////////////////////////////////////////////////////////////////////////// |
2084 procedure doStepSMine(Gear: PGear); |
2286 procedure doStepSMine(Gear: PGear); |
2107 doStepFallingGear(Gear); |
2309 doStepFallingGear(Gear); |
2108 AllInactive := false; |
2310 AllInactive := false; |
2109 CalcRotationDirAngle(Gear); |
2311 CalcRotationDirAngle(Gear); |
2110 end; |
2312 end; |
2111 |
2313 |
2314 Gear^.RenderTimer:= (Gear^.State and (gstFrozen or gstAttacking or gstDrowning) = 0); |
|
2112 if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then |
2315 if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then |
2113 begin |
2316 begin |
2114 if ((Gear^.State and gstAttacking) = 0) and ((Gear^.State and gstFrozen) = 0) then |
2317 if ((Gear^.State and gstAttacking) = 0) and ((Gear^.State and gstFrozen) = 0) then |
2115 begin |
2318 begin |
2116 if ((GameTicks and $1F) = 0) then |
2319 if ((GameTicks and $1F) = 0) then |
2146 AllInactive := false; |
2349 AllInactive := false; |
2147 |
2350 |
2148 if Gear^.Timer mod 166 = 0 then |
2351 if Gear^.Timer mod 166 = 0 then |
2149 inc(Gear^.Tag); |
2352 inc(Gear^.Tag); |
2150 if Gear^.Timer = 1000 then // might need better timing |
2353 if Gear^.Timer = 1000 then // might need better timing |
2151 makeHogsWorry(Gear^.X, Gear^.Y, 75); |
2354 makeHogsWorry(Gear^.X, Gear^.Y, 75, Gear^.Kind); |
2152 if Gear^.Timer = 0 then |
2355 if Gear^.Timer = 0 then |
2153 begin |
2356 begin |
2154 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
2357 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
2155 DeleteGear(Gear); |
2358 DeleteGear(Gear); |
2156 exit |
2359 exit |
2193 dmg:= hwRound(dxdy * _50); |
2396 dmg:= hwRound(dxdy * _50); |
2194 inc(Gear^.Damage, dmg); |
2397 inc(Gear^.Damage, dmg); |
2195 ScriptCall('onGearDamage', Gear^.UID, dmg) |
2398 ScriptCall('onGearDamage', Gear^.UID, dmg) |
2196 end; |
2399 end; |
2197 CalcRotationDirAngle(Gear); |
2400 CalcRotationDirAngle(Gear); |
2198 //CheckGearDrowning(Gear) |
|
2199 end |
2401 end |
2200 else |
2402 else |
2201 begin |
2403 begin |
2202 Gear^.State := Gear^.State or gsttmpFlag; |
2404 Gear^.State := Gear^.State or gsttmpFlag; |
2203 AddCI(Gear) |
2405 AddCI(Gear) |
2204 end; |
2406 end; |
2205 |
|
2206 (* |
|
2207 Attempt to make a barrel knock itself over an edge. Would need more checks to avoid issues like burn damage |
|
2208 begin |
|
2209 x:= hwRound(Gear^.X); |
|
2210 y:= hwRound(Gear^.Y); |
|
2211 if (((y+1) and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then |
|
2212 if (Land[y+1, x] = 0) then |
|
2213 begin |
|
2214 if (((y+1) and LAND_HEIGHT_MASK) = 0) and (((x+Gear^.Radius-2) and LAND_WIDTH_MASK) = 0) and (Land[y+1, x+Gear^.Radius-2] = 0) then |
|
2215 Gear^.dX:= -_0_08 |
|
2216 else if (((y+1 and LAND_HEIGHT_MASK)) = 0) and (((x-(Gear^.Radius-2)) and LAND_WIDTH_MASK) = 0) and (Land[y+1, x-(Gear^.Radius-2)] = 0) then |
|
2217 Gear^.dX:= _0_08; |
|
2218 end; |
|
2219 if Gear^.dX.QWordValue = 0 then AddCI(Gear) |
|
2220 end; *) |
|
2221 |
2407 |
2222 if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then |
2408 if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then |
2223 Gear^.dY := _0; |
2409 Gear^.dY := _0; |
2224 if hwAbs(Gear^.dX) < _0_001 then |
2410 if hwAbs(Gear^.dX) < _0_001 then |
2225 Gear^.dX := _0; |
2411 Gear^.dX := _0; |
2227 if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then |
2413 if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then |
2228 if (cBarrelHealth div Gear^.Health) > 2 then |
2414 if (cBarrelHealth div Gear^.Health) > 2 then |
2229 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke) |
2415 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke) |
2230 else |
2416 else |
2231 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite); |
2417 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite); |
2418 |
|
2232 dec(Gear^.Health, Gear^.Damage); |
2419 dec(Gear^.Health, Gear^.Damage); |
2233 Gear^.Damage := 0; |
2420 Gear^.Damage := 0; |
2234 if Gear^.Health <= 0 then |
2421 if Gear^.Health <= 0 then |
2235 doStepCase(Gear); |
2422 doStepCase(Gear) |
2423 else |
|
2424 // health texture (FlightTime = health when the last texture was generated) |
|
2425 if (Gear^.Health <> Gear^.FlightTime) or (Gear^.Tex = nil) then |
|
2426 begin |
|
2427 Gear^.FlightTime:= Gear^.Health; |
|
2428 FreeAndNilTexture(Gear^.Tex); |
|
2429 Gear^.Tex := RenderStringTex(ansistring(inttostr(Gear^.Health)), $ff808080, fnt16); |
|
2430 end; |
|
2236 end; |
2431 end; |
2237 |
2432 |
2238 procedure doStepCase(Gear: PGear); |
2433 procedure doStepCase(Gear: PGear); |
2239 var |
2434 var |
2240 i, x, y: LongInt; |
2435 i, x, y: LongInt; |
2262 begin |
2457 begin |
2263 x := hwRound(Gear^.X); |
2458 x := hwRound(Gear^.X); |
2264 y := hwRound(Gear^.Y); |
2459 y := hwRound(Gear^.Y); |
2265 hog:= Gear^.Hedgehog; |
2460 hog:= Gear^.Hedgehog; |
2266 |
2461 |
2267 DeleteGear(Gear); |
|
2268 // <-- delete gear! |
|
2269 |
|
2270 if k = gtCase then |
2462 if k = gtCase then |
2271 begin |
2463 begin |
2272 doMakeExplosion(x, y, Gear^.Boom, hog, EXPLAutoSound); |
2464 doMakeExplosion(x, y, Gear^.Boom, hog, EXPLAutoSound); |
2273 for i:= 0 to 63 do |
2465 for i:= 0 to 63 do |
2274 AddGear(x, y, gtFlame, 0, _0, _0, 0); |
2466 AddGear(x, y, gtFlame, 0, _0, _0, 0); |
2275 end |
2467 end |
2276 else if k = gtTarget then |
2468 else if k = gtTarget then |
2277 uStats.TargetHit() |
2469 uStats.TargetHit() |
2278 else if k = gtExplosives then |
2470 else if k = gtExplosives then |
2279 begin |
2471 begin |
2280 doMakeExplosion(x, y, Gear^.Boom, hog, EXPLAutoSound); |
2472 doMakeExplosion(x, y, Gear^.Boom, hog, EXPLAutoSound); |
2281 for i:= 0 to 31 do |
2473 for i:= 0 to 31 do |
2282 begin |
2474 begin |
2283 dX := AngleCos(i * 64) * _0_5 * (getrandomf + _1); |
2475 dX := AngleCos(i * 64) * _0_5 * (getrandomf + _1); |
2284 dY := AngleSin(i * 64) * _0_5 * (getrandomf + _1); |
2476 dY := AngleSin(i * 64) * _0_5 * (getrandomf + _1); |
2285 AddGear(x, y, gtFlame, 0, dX, dY, 0); |
2477 AddGear(x, y, gtFlame, 0, dX, dY, 0); |
2286 AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0); |
2478 AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0); |
2287 end |
2479 end |
2288 end; |
2480 end; |
2289 exit |
2481 DeleteGear(Gear); |
2482 exit |
|
2290 end; |
2483 end; |
2291 |
2484 |
2292 if k = gtExplosives then |
2485 if k = gtExplosives then |
2293 begin |
2486 begin |
2294 //if V > _0_03 then Gear^.State:= Gear^.State or gstAnimation; |
|
2295 if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02)) then |
2487 if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02)) then |
2296 begin |
2488 begin |
2297 Gear^.doStep := @doStepRollingBarrel; |
2489 Gear^.doStep := @doStepRollingBarrel; |
2298 exit; |
2490 exit; |
2299 end |
2491 end |
2302 if ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then |
2494 if ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then |
2303 if (cBarrelHealth div Gear^.Health) > 2 then |
2495 if (cBarrelHealth div Gear^.Health) > 2 then |
2304 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke) |
2496 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke) |
2305 else |
2497 else |
2306 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite); |
2498 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite); |
2499 |
|
2307 dec(Gear^.Health, Gear^.Damage); |
2500 dec(Gear^.Health, Gear^.Damage); |
2308 Gear^.Damage := 0; |
2501 Gear^.Damage := 0; |
2502 // health texture (FlightTime = health when the last texture was generated) |
|
2503 if (Gear^.Health <> Gear^.FlightTime) or (Gear^.Tex = nil) then |
|
2504 begin |
|
2505 Gear^.FlightTime:= Gear^.Health; |
|
2506 FreeAndNilTexture(Gear^.Tex); |
|
2507 Gear^.Tex := RenderStringTex(ansistring(inttostr(Gear^.Health)), $ff808080, fnt16); |
|
2508 end; |
|
2309 end |
2509 end |
2310 else |
2510 else |
2311 begin |
2511 begin |
2512 // health texture for health crate |
|
2513 if (k = gtCase) and ((Gear^.Pos and posCaseHealth) <> 0) then |
|
2514 begin |
|
2515 if ((Gear^.State and gstFrozen) = 0) then |
|
2516 begin |
|
2517 // Karma=2: Always hide health |
|
2518 if (Gear^.Karma = 2) then |
|
2519 i:= 0 |
|
2520 // Karma=1: Hide health in game, but show in demo |
|
2521 else if (Gear^.Karma = 1) then |
|
2522 if (GameType in [gmtDemo, gmtRecord]) then |
|
2523 i:= 1 |
|
2524 else |
|
2525 i:= 0 |
|
2526 // Always show health (default) |
|
2527 else |
|
2528 i:= 1; |
|
2529 if i = 1 then |
|
2530 begin |
|
2531 if (Gear^.Health <> Gear^.FlightTime) or (Gear^.Tex = nil) then |
|
2532 begin |
|
2533 Gear^.FlightTime:= Gear^.Health; |
|
2534 FreeAndNilTexture(Gear^.Tex); |
|
2535 Gear^.Tex := RenderStringTex(ansistring(inttostr(Gear^.Health)), $ff80ff80, fnt16) |
|
2536 end |
|
2537 end |
|
2538 else |
|
2539 begin |
|
2540 if (Gear^.FlightTime <> $ffffffff) or (Gear^.Tex = nil) then |
|
2541 begin |
|
2542 Gear^.FlightTime:= $ffffffff; |
|
2543 FreeAndNilTexture(Gear^.Tex); |
|
2544 Gear^.Tex := RenderStringTex(trmsg[sidUnknownGearValue], $ff80ff80, fnt16) |
|
2545 end |
|
2546 end |
|
2547 end; |
|
2548 end; |
|
2312 if Gear^.Timer = 500 then |
2549 if Gear^.Timer = 500 then |
2313 begin |
2550 begin |
2314 (* Can't make sparkles team coloured without working out what the next team is going to be. This should be solved, really, since it also screws up |
2551 (* Can't make sparkles team coloured without working out what the next team is going to be. This should be solved, really, since it also screws up |
2315 voices. Reinforcements voices is heard for active team, not team-to-be. Either that or change crate spawn from end of turn to start, although that |
2552 voices. Reinforcements voices is heard for active team, not team-to-be. Either that or change crate spawn from end of turn to start, although that |
2316 has its own complexities. *) |
2553 has its own complexities. *) |
2369 if Gear^.dY > - _0_001 then |
2606 if Gear^.dY > - _0_001 then |
2370 Gear^.dY := _0 |
2607 Gear^.dY := _0 |
2371 else if Gear^.dY < - _0_03 then |
2608 else if Gear^.dY < - _0_03 then |
2372 PlaySound(Gear^.ImpactSound); |
2609 PlaySound(Gear^.ImpactSound); |
2373 end; |
2610 end; |
2374 //if Gear^.dY > - _0_001 then Gear^.dY:= _0 |
|
2375 CheckGearDrowning(Gear); |
2611 CheckGearDrowning(Gear); |
2612 if ((Gear^.State and gstDrowning) <> 0) then |
|
2613 Gear^.RenderHealth:= false; |
|
2376 end; |
2614 end; |
2377 |
2615 |
2378 if (Gear^.dY.QWordValue = 0) then |
2616 if (Gear^.dY.QWordValue = 0) then |
2379 AddCI(Gear) |
2617 AddCI(Gear) |
2380 else if (Gear^.dY.QWordValue <> 0) then |
2618 else if (Gear^.dY.QWordValue <> 0) then |
2427 begin |
2665 begin |
2428 dec(Gear^.Timer); |
2666 dec(Gear^.Timer); |
2429 if Gear^.Timer = 0 then |
2667 if Gear^.Timer = 0 then |
2430 begin |
2668 begin |
2431 inc(Gear^.Tag); |
2669 inc(Gear^.Tag); |
2432 Gear^.Timer := 50 |
2670 Gear^.Timer := 50; |
2671 if Gear^.Tag = 3 then |
|
2672 begin |
|
2673 ClearHitOrder(); |
|
2674 RefillProximityCache(Gear, 100); |
|
2675 end; |
|
2433 end; |
2676 end; |
2434 |
2677 |
2435 if Gear^.Tag = 3 then |
2678 if Gear^.Tag = 3 then |
2436 begin |
2679 begin |
2437 HHGear := Gear^.Hedgehog^.Gear; |
2680 HHGear := Gear^.Hedgehog^.Gear; |
2438 HHGear^.State := HHGear^.State or gstNoDamage; |
2681 HHGear^.State := HHGear^.State or gstNoDamage; |
2439 DeleteCI(HHGear); |
2682 DeleteCI(HHGear); |
2440 |
2683 |
2441 AmmoShove(Gear, Gear^.Boom, 115); |
2684 AmmoShoveCache(Gear, Gear^.Boom, 115); |
2442 |
2685 |
2443 HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving; |
2686 HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving; |
2444 end |
2687 end |
2445 else if Gear^.Tag = 4 then |
2688 else if Gear^.Tag = 4 then |
2446 begin |
2689 begin |
2690 ClearHitOrder(); |
|
2691 ClearProximityCache(); |
|
2447 Gear^.Timer := 250; |
2692 Gear^.Timer := 250; |
2448 Gear^.doStep := @doStepIdle |
2693 Gear^.doStep := @doStepIdle |
2449 end |
2694 end |
2450 end; |
2695 end; |
2451 |
2696 |
2457 begin |
2702 begin |
2458 HHGear := Gear^.Hedgehog^.Gear; |
2703 HHGear := Gear^.Hedgehog^.Gear; |
2459 HHGear^.State := HHGear^.State or gstNoDamage; |
2704 HHGear^.State := HHGear^.State or gstNoDamage; |
2460 DeleteCI(HHGear); |
2705 DeleteCI(HHGear); |
2461 |
2706 |
2707 ClearHitOrder(); |
|
2708 RefillProximityCache(Gear, 100); |
|
2462 for i:= 0 to 3 do |
2709 for i:= 0 to 3 do |
2463 begin |
2710 begin |
2464 AddVisualGear(hwRound(Gear^.X) + hwSign(Gear^.dX) * (10 + 6 * i), hwRound(Gear^.Y) + 12 + Random(6), vgtDust); |
2711 AddVisualGear(hwRound(Gear^.X) + hwSign(Gear^.dX) * (10 + 6 * i), hwRound(Gear^.Y) + 12 + Random(6), vgtDust); |
2465 AmmoShove(Gear, Gear^.Boom, 25); |
2712 AmmoShoveCache(Gear, Gear^.Boom, 25); |
2466 Gear^.X := Gear^.X + Gear^.dX * 5 |
2713 Gear^.X := Gear^.X + Gear^.dX * 5 |
2467 end; |
2714 end; |
2468 |
2715 |
2716 ClearHitOrder(); |
|
2717 ClearProximityCache(); |
|
2469 HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving; |
2718 HHGear^.State := (HHGear^.State and (not gstNoDamage)) or gstMoving; |
2470 |
2719 |
2471 Gear^.Timer := 250; |
2720 Gear^.Timer := 250; |
2472 Gear^.doStep := @doStepIdle |
2721 Gear^.doStep := @doStepIdle |
2473 end; |
2722 end; |
2481 tdX,tdY, f: HWFloat; |
2730 tdX,tdY, f: HWFloat; |
2482 landPixel: Word; |
2731 landPixel: Word; |
2483 begin |
2732 begin |
2484 WorldWrap(Gear); |
2733 WorldWrap(Gear); |
2485 if Gear^.FlightTime > 0 then dec(Gear^.FlightTime); |
2734 if Gear^.FlightTime > 0 then dec(Gear^.FlightTime); |
2735 // There are 2 flame types: normal and sticky |
|
2486 sticky:= (Gear^.State and gsttmpFlag) <> 0; |
2736 sticky:= (Gear^.State and gsttmpFlag) <> 0; |
2487 if not sticky then AllInactive := false; |
2737 if not sticky then AllInactive := false; |
2488 |
2738 |
2489 landPixel:= TestCollisionYwithGear(Gear, 1); |
2739 landPixel:= TestCollisionYwithGear(Gear, 1); |
2740 // Flame is in mid-air |
|
2490 if landPixel = 0 then |
2741 if landPixel = 0 then |
2491 begin |
2742 begin |
2492 AllInactive := false; |
2743 AllInactive := false; |
2493 |
2744 |
2745 // Deals damage in mid-air if FlightTime = 0. |
|
2746 // Otherwise, flame is harmless in mid-air. |
|
2747 // Intended for use with scripts. |
|
2494 if (GameTicks and $F = 0) and (Gear^.FlightTime = 0) then |
2748 if (GameTicks and $F = 0) and (Gear^.FlightTime = 0) then |
2495 begin |
2749 begin |
2496 Gear^.Radius := 7; |
2750 Gear^.Radius := 7; |
2497 tdX:= Gear^.dX; |
2751 tdX:= Gear^.dX; |
2498 tdY:= Gear^.dY; |
2752 tdY:= Gear^.dY; |
2502 Gear^.dY.isNegative:= true; |
2756 Gear^.dY.isNegative:= true; |
2503 AmmoShove(Gear, Gear^.Boom, 125); |
2757 AmmoShove(Gear, Gear^.Boom, 125); |
2504 Gear^.dX:= tdX; |
2758 Gear^.dX:= tdX; |
2505 Gear^.dY:= tdY; |
2759 Gear^.dY:= tdY; |
2506 Gear^.Radius := 1 |
2760 Gear^.Radius := 1 |
2507 end; |
2761 end; |
2508 |
2762 |
2509 if ((GameTicks mod 100) = 0) then |
2763 if ((GameTicks mod 100) = 0) then |
2510 begin |
2764 begin |
2511 vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire, gstTmpFlag); |
2765 vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire, gstTmpFlag); |
2512 if vgt <> nil then |
2766 if vgt <> nil then |
2525 f:= _1_9 / Distance(Gear^.dX, Gear^.dY); |
2779 f:= _1_9 / Distance(Gear^.dX, Gear^.dY); |
2526 Gear^.dX:= Gear^.dX * f; |
2780 Gear^.dX:= Gear^.dX * f; |
2527 Gear^.dY:= Gear^.dY * f; |
2781 Gear^.dY:= Gear^.dY * f; |
2528 end |
2782 end |
2529 else begin |
2783 else begin |
2784 // Gravity and wind |
|
2530 if Gear^.dX.QWordValue > _0_01.QWordValue then |
2785 if Gear^.dX.QWordValue > _0_01.QWordValue then |
2531 Gear^.dX := Gear^.dX * _0_995; |
2786 Gear^.dX := Gear^.dX * _0_995; |
2532 |
2787 |
2533 Gear^.dY := Gear^.dY + cGravity; |
2788 Gear^.dY := Gear^.dY + cGravity; |
2534 // if sticky then Gear^.dY := Gear^.dY + cGravity; |
|
2535 |
2789 |
2536 if Gear^.dY.QWordValue > _0_2.QWordValue then |
2790 if Gear^.dY.QWordValue > _0_2.QWordValue then |
2537 Gear^.dY := Gear^.dY * _0_995; |
2791 Gear^.dY := Gear^.dY * _0_995; |
2538 |
2792 |
2539 //if sticky then Gear^.X := Gear^.X + Gear^.dX else |
2793 // Apply speed changes |
2540 Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640; |
2794 |
2795 tdX:= Gear^.dX + cWindSpeed * 640; |
|
2796 // Don't apply wind speed if moving against bounce world edge |
|
2797 if (WorldEdge = weBounce) and |
|
2798 (((hwRound(Gear^.X + tdX) - Gear^.Radius < leftX) and (hwSign(tdX) = -1)) or |
|
2799 ((hwRound(Gear^.X + tdX) + Gear^.Radius > rightX) and (hwSign(tdX) = 1))) then |
|
2800 Gear^.X := Gear^.X + Gear^.dX |
|
2801 else |
|
2802 // Apply dX and wind speed |
|
2803 Gear^.X := Gear^.X + tdX; |
|
2804 |
|
2541 Gear^.Y := Gear^.Y + Gear^.dY; |
2805 Gear^.Y := Gear^.Y + Gear^.dY; |
2542 end; |
2806 end; |
2543 |
2807 |
2544 gX := hwRound(Gear^.X); |
2808 gX := hwRound(Gear^.X); |
2545 gY := hwRound(Gear^.Y); |
2809 gY := hwRound(Gear^.Y); |
2546 |
2810 |
2811 // Extinguish in water |
|
2547 if CheckCoordInWater(gX, gY) then |
2812 if CheckCoordInWater(gX, gY) then |
2548 begin |
2813 begin |
2549 for i:= 0 to 3 do |
2814 for i:= 0 to 3 do |
2550 AddVisualGear(gX - 8 + Random(16), gY - 8 + Random(16), vgtSteam); |
2815 AddVisualGear(gX - 8 + Random(16), gY - 8 + Random(16), vgtSteam); |
2551 PlaySound(sndVaporize); |
2816 PlaySound(sndVaporize); |
2552 DeleteGear(Gear); |
2817 DeleteGear(Gear); |
2553 exit |
2818 exit |
2554 end |
2819 end |
2555 end |
2820 end |
2821 // Flame is on terrain |
|
2556 else |
2822 else |
2557 begin |
2823 begin |
2558 if (Gear^.Timer = 1) and (GameTicks and $3 = 0) then |
2824 if (Gear^.Timer = 1) and (GameTicks and $3 = 0) then |
2559 begin |
2825 begin |
2560 Gear^.Y:= Gear^.Y+_6; |
2826 Gear^.Y:= Gear^.Y+_6; |
2827 // Extinguish on ice |
|
2561 if (landPixel and lfIce <> 0) or (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then |
2828 if (landPixel and lfIce <> 0) or (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then |
2562 begin |
2829 begin |
2563 gX := hwRound(Gear^.X); |
2830 gX := hwRound(Gear^.X); |
2564 gY := hwRound(Gear^.Y) - 6; |
2831 gY := hwRound(Gear^.Y) - 6; |
2565 DrawExplosion(gX, gY, 4); |
2832 doMakeExplosion(gX, gY, 4, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx); |
2566 PlaySound(sndVaporize); |
2833 PlaySound(sndVaporize); |
2567 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSteam); |
2834 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSteam); |
2568 DeleteGear(Gear); |
2835 DeleteGear(Gear); |
2569 exit |
2836 exit |
2570 end; |
2837 end; |
2571 Gear^.Y:= Gear^.Y-_6 |
2838 Gear^.Y:= Gear^.Y-_6 |
2572 end; |
2839 end; |
2840 // Sticky flame damage |
|
2573 if sticky and (GameTicks and $F = 0) then |
2841 if sticky and (GameTicks and $F = 0) then |
2574 begin |
2842 begin |
2575 Gear^.Radius := 7; |
2843 Gear^.Radius := 7; |
2576 tdX:= Gear^.dX; |
2844 tdX:= Gear^.dX; |
2577 tdY:= Gear^.dY; |
2845 tdY:= Gear^.dY; |
2588 begin |
2856 begin |
2589 dec(Gear^.Timer); |
2857 dec(Gear^.Timer); |
2590 inc(Gear^.Damage) |
2858 inc(Gear^.Damage) |
2591 end |
2859 end |
2592 else |
2860 else |
2861 // Flame burn-down handling |
|
2593 begin |
2862 begin |
2594 gX := hwRound(Gear^.X); |
2863 gX := hwRound(Gear^.X); |
2595 gY := hwRound(Gear^.Y); |
2864 gY := hwRound(Gear^.Y); |
2596 // Standard fire |
2865 // Normal flame: Burns down quickly and must be destroyed before the turn ends |
2597 if not sticky then |
2866 if not sticky then |
2598 begin |
2867 begin |
2868 // Deal damage |
|
2599 if ((GameTicks and $1) = 0) then |
2869 if ((GameTicks and $1) = 0) then |
2600 begin |
2870 begin |
2601 Gear^.Radius := 7; |
2871 Gear^.Radius := 7; |
2602 tdX:= Gear^.dX; |
2872 tdX:= Gear^.dX; |
2603 tdY:= Gear^.dY; |
2873 tdY:= Gear^.dY; |
2609 Gear^.dX:= tdX; |
2879 Gear^.dX:= tdX; |
2610 Gear^.dY:= tdY; |
2880 Gear^.dY:= tdY; |
2611 Gear^.Radius := 1; |
2881 Gear^.Radius := 1; |
2612 end |
2882 end |
2613 else if ((GameTicks and $3) = 3) then |
2883 else if ((GameTicks and $3) = 3) then |
2614 doMakeExplosion(gX, gY, Gear^.Boom * 4, Gear^.Hedgehog, 0);//, EXPLNoDamage); |
2884 doMakeExplosion(gX, gY, Gear^.Boom * 4, Gear^.Hedgehog, 0); |
2615 //DrawExplosion(gX, gY, 4); |
|
2616 |
2885 |
2617 if ((GameTicks and $7) = 0) and (Random(2) = 0) then |
2886 if ((GameTicks and $7) = 0) and (Random(2) = 0) then |
2618 for i:= Random(2) downto 0 do |
2887 for i:= Random(2) downto 0 do |
2619 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke); |
2888 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke); |
2620 |
2889 |
2890 // Flame burn-out due to time |
|
2621 if Gear^.Health > 0 then |
2891 if Gear^.Health > 0 then |
2622 dec(Gear^.Health); |
2892 dec(Gear^.Health); |
2893 |
|
2894 // Calculate time for next flame update with a bit of random jitter |
|
2623 Gear^.Timer := 450 - Gear^.Tag * 8 + LongInt(GetRandom(2)) |
2895 Gear^.Timer := 450 - Gear^.Tag * 8 + LongInt(GetRandom(2)) |
2624 end |
2896 end |
2897 // Sticky flame: Burns down slowly and persists between turns |
|
2625 else |
2898 else |
2626 begin |
2899 begin |
2627 // Modified fire |
2900 // Destroy land very slowly (low chance this gets called) |
2628 if ((GameTicks and $7FF) = 0) and ((GameFlags and gfSolidLand) = 0) then |
2901 if ((GameTicks and $7FF) = 0) and ((GameFlags and gfSolidLand) = 0) then |
2629 begin |
2902 begin |
2630 DrawExplosion(gX, gY, 4); |
2903 doMakeExplosion(gX, gY, 4, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx); |
2631 |
2904 |
2632 for i:= Random(3) downto 0 do |
2905 for i:= Random(3) downto 0 do |
2633 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke); |
2906 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke); |
2634 end; |
2907 end; |
2635 |
2908 |
2636 // This one is interesting. I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom. |
2909 // Calculate time for next flame update with a bit of random jitter |
2637 Gear^.Timer := 100 - Gear^.Tag * 3 + LongInt(GetRandom(2)); |
2910 Gear^.Timer := 100 - Gear^.Tag * 3 + LongInt(GetRandom(2)); |
2911 |
|
2912 // Flame burn-out due to time |
|
2638 if (Gear^.Damage > 3000+Gear^.Tag*1500) then |
2913 if (Gear^.Damage > 3000+Gear^.Tag*1500) then |
2639 Gear^.Health := 0 |
2914 Gear^.Health := 0 |
2640 end |
2915 end |
2641 end |
2916 end |
2642 end; |
2917 end; |
2918 // This kills the flame |
|
2643 if Gear^.Health = 0 then |
2919 if Gear^.Health = 0 then |
2644 begin |
2920 begin |
2645 gX := hwRound(Gear^.X); |
2921 gX := hwRound(Gear^.X); |
2646 gY := hwRound(Gear^.Y); |
2922 gY := hwRound(Gear^.Y); |
2647 if not sticky then |
2923 if not sticky then |
2653 else |
2929 else |
2654 for i:= Random(3) downto 0 do |
2930 for i:= Random(3) downto 0 do |
2655 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke); |
2931 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke); |
2656 |
2932 |
2657 DeleteGear(Gear) |
2933 DeleteGear(Gear) |
2658 end; |
2934 end |
2659 end; |
2935 end; |
2660 |
2936 |
2661 //////////////////////////////////////////////////////////////////////////////// |
2937 //////////////////////////////////////////////////////////////////////////////// |
2662 procedure doStepFirePunchWork(Gear: PGear); |
2938 procedure doStepFirePunchWork(Gear: PGear); |
2663 var |
2939 var |
2676 begin |
2952 begin |
2677 Gear^.Tag := hwRound(HHGear^.Y); |
2953 Gear^.Tag := hwRound(HHGear^.Y); |
2678 DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4+2, 2); |
2954 DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4+2, 2); |
2679 HHGear^.State := HHGear^.State or gstNoDamage; |
2955 HHGear^.State := HHGear^.State or gstNoDamage; |
2680 Gear^.Y := HHGear^.Y; |
2956 Gear^.Y := HHGear^.Y; |
2681 AmmoShove(Gear, Gear^.Boom, 40); |
2957 AmmoShoveCache(Gear, Gear^.Boom, 40); |
2682 HHGear^.State := HHGear^.State and (not gstNoDamage) |
2958 HHGear^.State := HHGear^.State and (not gstNoDamage) |
2683 end; |
2959 end; |
2684 |
2960 |
2685 HHGear^.dY := HHGear^.dY + cGravity; |
2961 HHGear^.dY := HHGear^.dY + cGravity; |
2686 if Gear^.Timer > 0 then dec(Gear^.Timer); |
2962 if Gear^.Timer > 0 then dec(Gear^.Timer); |
2687 if not (HHGear^.dY.isNegative) or (Gear^.Timer = 0) then |
2963 if not (HHGear^.dY.isNegative) or (Gear^.Timer = 0) then |
2688 begin |
2964 begin |
2689 HHGear^.State := HHGear^.State or gstMoving; |
2965 HHGear^.State := HHGear^.State or gstMoving; |
2966 ClearHitOrder(); |
|
2967 ClearProximityCache(); |
|
2690 DeleteGear(Gear); |
2968 DeleteGear(Gear); |
2691 AfterAttack; |
2969 AfterAttack; |
2692 exit |
2970 exit |
2693 end; |
2971 end; |
2694 |
2972 |
2695 if CheckLandValue(hwRound(HHGear^.X), hwRound(HHGear^.Y + HHGear^.dY + SignAs(_6,Gear^.dY)), |
2973 if CheckLandValue(hwRound(HHGear^.X), hwRound(HHGear^.Y + HHGear^.dY + SignAs(_6,Gear^.dY)), |
2696 lfIndestructible) then |
2974 lfIndestructible) then |
2697 HHGear^.Y := HHGear^.Y + HHGear^.dY |
2975 HHGear^.Y := HHGear^.Y + HHGear^.dY; |
2976 |
|
2977 if (Gear^.Timer mod 200) = 0 then |
|
2978 RefillProximityCache(Gear, 300); |
|
2698 end; |
2979 end; |
2699 |
2980 |
2700 procedure doStepFirePunch(Gear: PGear); |
2981 procedure doStepFirePunch(Gear: PGear); |
2701 var |
2982 var |
2702 HHGear: PGear; |
2983 HHGear: PGear; |
2703 begin |
2984 begin |
2704 AllInactive := false; |
2985 AllInactive := false; |
2705 HHGear := Gear^.Hedgehog^.Gear; |
2986 HHGear := Gear^.Hedgehog^.Gear; |
2706 DeleteCI(HHGear); |
2987 DeleteCI(HHGear); |
2707 //HHGear^.X := int2hwFloat(hwRound(HHGear^.X)) - _0_5; WTF? |
|
2708 HHGear^.dX := SignAs(cLittle, Gear^.dX); |
2988 HHGear^.dX := SignAs(cLittle, Gear^.dX); |
2709 |
2989 |
2710 HHGear^.dY := - _0_3; |
2990 HHGear^.dY := - _0_3; |
2991 |
|
2992 ClearHitOrder(); |
|
2993 RefillProximityCache(Gear, 300); |
|
2711 |
2994 |
2712 Gear^.X := HHGear^.X; |
2995 Gear^.X := HHGear^.X; |
2713 Gear^.dX := SignAs(_0_45, Gear^.dX); |
2996 Gear^.dX := SignAs(_0_45, Gear^.dX); |
2714 Gear^.dY := - _0_9; |
2997 Gear^.dY := - _0_9; |
2715 Gear^.doStep := @doStepFirePunchWork; |
2998 Gear^.doStep := @doStepFirePunchWork; |
2721 //////////////////////////////////////////////////////////////////////////////// |
3004 //////////////////////////////////////////////////////////////////////////////// |
2722 |
3005 |
2723 procedure doStepParachuteWork(Gear: PGear); |
3006 procedure doStepParachuteWork(Gear: PGear); |
2724 var |
3007 var |
2725 HHGear: PGear; |
3008 HHGear: PGear; |
3009 deltaX, deltaY: hwFloat; |
|
2726 begin |
3010 begin |
2727 HHGear := Gear^.Hedgehog^.Gear; |
3011 HHGear := Gear^.Hedgehog^.Gear; |
2728 |
3012 |
2729 inc(Gear^.Timer); |
3013 inc(Gear^.Timer); |
2730 |
3014 |
2734 or ((Gear^.Message and gmAttack) <> 0) then |
3018 or ((Gear^.Message and gmAttack) <> 0) then |
2735 begin |
3019 begin |
2736 with HHGear^ do |
3020 with HHGear^ do |
2737 begin |
3021 begin |
2738 Message := 0; |
3022 Message := 0; |
3023 if Gear^.Tag = 1 then |
|
3024 dX := _1 |
|
3025 else |
|
3026 dX := - _1; |
|
2739 SetLittle(dX); |
3027 SetLittle(dX); |
2740 dY := _0; |
3028 dY := _0; |
2741 State := State or gstMoving; |
3029 State := State or gstMoving; |
2742 end; |
3030 end; |
2743 DeleteGear(Gear); |
3031 if (GetAmmoEntry(HHGear^.Hedgehog^, amParachute)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) and (HHGear^.Hedgehog^.MultiShootAttacks = 0) then |
2744 if (GetAmmoEntry(HHGear^.Hedgehog^, amParachute)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then |
|
2745 HHGear^.Hedgehog^.CurAmmoType:= amParachute; |
3032 HHGear^.Hedgehog^.CurAmmoType:= amParachute; |
2746 isCursorVisible := false; |
3033 isCursorVisible := false; |
2747 ApplyAmmoChanges(HHGear^.Hedgehog^); |
3034 ApplyAmmoChanges(HHGear^.Hedgehog^); |
3035 DeleteGear(Gear); |
|
2748 exit |
3036 exit |
2749 end; |
3037 end; |
2750 |
3038 |
2751 HHGear^.X := HHGear^.X + cWindSpeed * 200; |
3039 deltaX:= _0; |
3040 deltaX:= deltaX + cWindSpeed * 200; |
|
3041 deltaY:= _0; |
|
2752 |
3042 |
2753 if (Gear^.Message and gmLeft) <> 0 then |
3043 if (Gear^.Message and gmLeft) <> 0 then |
2754 HHGear^.X := HHGear^.X - cMaxWindSpeed * 80 |
3044 deltaX := deltaX - cMaxWindSpeed * 80 |
2755 |
3045 |
2756 else if (Gear^.Message and gmRight) <> 0 then |
3046 else if (Gear^.Message and gmRight) <> 0 then |
2757 HHGear^.X := HHGear^.X + cMaxWindSpeed * 80; |
3047 deltaX := deltaX + cMaxWindSpeed * 80; |
2758 |
3048 |
2759 if (Gear^.Message and gmUp) <> 0 then |
3049 if (Gear^.Message and gmUp) <> 0 then |
2760 HHGear^.Y := HHGear^.Y - cGravity * 40 |
3050 deltaY := deltaY - cGravity * 40 |
2761 |
3051 |
2762 else if (Gear^.Message and gmDown) <> 0 then |
3052 else if (Gear^.Message and gmDown) <> 0 then |
2763 HHGear^.Y := HHGear^.Y + cGravity * 40; |
3053 deltaY := deltaY + cGravity * 40; |
2764 |
3054 |
3055 HHGear^.X := HHGear^.X + deltaX; |
|
2765 // don't drift into obstacles |
3056 // don't drift into obstacles |
2766 if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) <> 0 then |
3057 if TestCollisionXwithGear(HHGear, hwSign(deltaX)) <> 0 then |
2767 HHGear^.X := HHGear^.X - int2hwFloat(hwSign(HHGear^.dX)); |
3058 begin |
2768 HHGear^.Y := HHGear^.Y + cGravity * 100; |
3059 HHGear^.X := HHGear^.X - int2hwFloat(hwSign(deltaX)); |
3060 deltaX:= _0; |
|
3061 end; |
|
3062 deltaY := deltaY + cGravity * 100; |
|
3063 HHGear^.Y := HHGear^.Y + deltaY; |
|
3064 |
|
3065 HHGear^.dX := deltaX; |
|
3066 HHGear^.dY := deltaY; |
|
3067 |
|
2769 Gear^.X := HHGear^.X; |
3068 Gear^.X := HHGear^.X; |
2770 Gear^.Y := HHGear^.Y |
3069 Gear^.Y := HHGear^.Y |
2771 end; |
3070 end; |
2772 |
3071 |
2773 procedure doStepParachute(Gear: PGear); |
3072 procedure doStepParachute(Gear: PGear); |
2793 doStepParachuteWork(Gear) |
3092 doStepParachuteWork(Gear) |
2794 end; |
3093 end; |
2795 |
3094 |
2796 //////////////////////////////////////////////////////////////////////////////// |
3095 //////////////////////////////////////////////////////////////////////////////// |
2797 procedure doStepAirAttackWork(Gear: PGear); |
3096 procedure doStepAirAttackWork(Gear: PGear); |
3097 var uw, nuw: boolean; |
|
3098 tmpFloat: hwFloat; |
|
3099 i: LongInt; |
|
2798 begin |
3100 begin |
2799 AllInactive := false; |
3101 AllInactive := false; |
3102 if (WorldEdge = weWrap) then |
|
3103 if (WorldWrap(Gear)) then |
|
3104 inc(Gear^.Power); |
|
2800 Gear^.X := Gear^.X + cAirPlaneSpeed * Gear^.Tag; |
3105 Gear^.X := Gear^.X + cAirPlaneSpeed * Gear^.Tag; |
2801 |
3106 if (Gear^.Health > 0) and (Gear^.Power >= Gear^.WDTimer) and (((Gear^.Tag = 1) and (not (Gear^.X < Gear^.dX))) or ((Gear^.Tag = -1) and (not (Gear^.X > Gear^.dX)))) then |
2802 if (Gear^.Health > 0) and (not (Gear^.X < Gear^.dX)) and (Gear^.X < Gear^.dX + cAirPlaneSpeed) then |
|
2803 begin |
3107 begin |
2804 dec(Gear^.Health); |
3108 dec(Gear^.Health); |
2805 case Gear^.State of |
3109 Gear^.FlightTime:= 0; |
2806 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0); |
3110 // Spawn missile |
2807 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine, 0, cBombsSpeed * Gear^.Tag, _0, 0); |
3111 case Gear^.State of |
2808 2: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtNapalmBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0); |
3112 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0); |
2809 3: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtDrill, gsttmpFlag, cBombsSpeed * Gear^.Tag, _0, Gear^.Timer + 1); |
3113 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine, 0, cBombsSpeed * Gear^.Tag, _0, 0); |
2810 //4: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtWaterMelon, 0, cBombsSpeed * |
3114 2: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtNapalmBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0); |
2811 // Gear^.Tag, _0, 5000); |
3115 3: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtDrill, gsttmpFlag, cBombsSpeed * Gear^.Tag, _0, Gear^.Timer + 1); |
2812 end; |
3116 end; |
2813 Gear^.dX := Gear^.dX + int2hwFloat(Gear^.Damage * Gear^.Tag); |
3117 Gear^.dX := Gear^.X + int2hwFloat(Gear^.Damage * Gear^.Tag); |
3118 if (WorldEdge = weWrap) then |
|
3119 begin |
|
3120 Gear^.dX := int2hwFloat(CalcWorldWrap(hwRound(Gear^.dX), 0)); |
|
3121 if (((Gear^.Tag = 1) and (not (Gear^.X < Gear^.dX))) or ((Gear^.Tag = -1) and (not (Gear^.X > Gear^.dX)))) then |
|
3122 inc(Gear^.WDTimer); |
|
3123 end; |
|
3124 |
|
2814 if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then |
3125 if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then |
2815 FollowGear^.State:= FollowGear^.State or gstSubmersible; |
3126 FollowGear^.State:= FollowGear^.State or gstSubmersible; |
3127 end; |
|
3128 |
|
3129 if (Gear^.Health = 0) then |
|
3130 inc(Gear^.FlightTime); |
|
3131 |
|
3132 if (Gear^.SoundChannel <> -1) and (WorldEdge <> weSea) and (Gear^.FlightTime > 20) then |
|
3133 begin |
|
2816 StopSoundChan(Gear^.SoundChannel, 4000); |
3134 StopSoundChan(Gear^.SoundChannel, 4000); |
2817 end; |
3135 Gear^.SoundChannel := -1; |
2818 |
3136 end; |
3137 |
|
3138 // Particles |
|
2819 if (GameTicks and $3F) = 0 then |
3139 if (GameTicks and $3F) = 0 then |
2820 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
3140 if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then |
2821 |
3141 begin |
2822 if (hwRound(Gear^.X) > (max(LAND_WIDTH,4096)+2048)) or (hwRound(Gear^.X) < -2048) then |
3142 // air plane bubbles |
2823 begin |
3143 for i:=1 to 3 do |
2824 // avoid to play forever (is this necessary?) |
3144 AddVisualGear(hwRound(Gear^.X) - 8 + Random(16), hwRound(Gear^.Y) - 8 + Random(16), vgtBubble); |
3145 // pilot's snorkel bubbles |
|
3146 if random(2) = 0 then |
|
3147 AddVisualGear(hwRound(Gear^.X) + 10, hwRound(Gear^.Y) - 50, vgtBubble); |
|
3148 end |
|
3149 else |
|
3150 // smoke |
|
3151 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
|
3152 |
|
3153 // Get rid of gear and cleanup |
|
3154 if ((WorldEdge = weWrap) and (Gear^.FlightTime >= 4000)) or |
|
3155 ((WorldEdge <> weWrap) and (((hwRound(Gear^.X) - Gear^.Radius > (max(LAND_WIDTH,4096)+2048)) or (hwRound(Gear^.X) + Gear^.Radius < -2048) or ((Gear^.Message and gmDestroy) > 0)))) then |
|
3156 begin |
|
3157 // fail-safe: instanly stop sound if it wasn't disabled before |
|
3158 if (Gear^.SoundChannel <> -1) then |
|
3159 begin |
|
3160 StopSoundChan(Gear^.SoundChannel); |
|
3161 Gear^.SoundChannel := -1; |
|
3162 end; |
|
3163 if (WorldEdge = weWrap) then |
|
3164 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBigExplosion); |
|
3165 DeleteGear(Gear); |
|
3166 exit; |
|
3167 end; |
|
3168 |
|
3169 uw := (Gear^.Karma <> 0); // Was plane underwater last tick? |
|
3170 nuw := CheckCoordInWater(hwRound(Gear^.X) + Gear^.Radius * Gear^.Tag, hwRound(Gear^.Y)); // Is plane underwater now? |
|
3171 |
|
3172 // if water entered or left |
|
3173 if nuw <> uw then |
|
3174 begin |
|
3175 tmpFloat:= Gear^.dX; |
|
3176 Gear^.dX := cAirPlaneSpeed * Gear^.Tag; |
|
3177 AddSplashForGear(Gear, false); |
|
3178 Gear^.dX := tmpFloat; |
|
2825 StopSoundChan(Gear^.SoundChannel); |
3179 StopSoundChan(Gear^.SoundChannel); |
2826 DeleteGear(Gear) |
3180 if nuw then |
2827 end; |
3181 begin |
3182 Gear^.SoundChannel := LoopSound(sndPlaneWater); |
|
3183 StopSoundChan(Gear^.SoundChannel, 4000); |
|
3184 Gear^.SoundChannel := -1; |
|
3185 Gear^.Karma := 1; |
|
3186 end |
|
3187 else |
|
3188 begin |
|
3189 Gear^.SoundChannel := LoopSound(sndPlane); |
|
3190 Gear^.Karma := 0; |
|
3191 end; |
|
3192 end; |
|
3193 |
|
2828 end; |
3194 end; |
2829 |
3195 |
2830 procedure doStepAirAttack(Gear: PGear); |
3196 procedure doStepAirAttack(Gear: PGear); |
3197 var HHGear: PGear; |
|
2831 begin |
3198 begin |
2832 AllInactive := false; |
3199 AllInactive := false; |
2833 |
3200 |
3201 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
|
3202 HHGear:= Gear^.Hedgehog^.Gear; |
|
3203 |
|
3204 if (HHGear <> nil) then |
|
3205 PlaySoundV(sndIncoming, Gear^.Hedgehog^.Team^.voicepack); |
|
3206 AfterAttack; |
|
3207 CurAmmoGear := nil; |
|
3208 |
|
2834 if Gear^.X.QWordValue = 0 then |
3209 if Gear^.X.QWordValue = 0 then |
2835 begin |
3210 begin |
2836 Gear^.Tag := 1; |
3211 Gear^.Tag := 1; |
2837 Gear^.X := -_2048; |
3212 if (WorldEdge = weWrap) then |
3213 Gear^.X := int2hwFloat(CalcWorldWrap(Gear^.Target.X + max(384, LAND_WIDTH shr 2), 0)) |
|
3214 else |
|
3215 Gear^.X := -_2048; |
|
2838 end |
3216 end |
2839 else |
3217 else |
2840 begin |
3218 begin |
2841 Gear^.Tag := -1; |
3219 Gear^.Tag := -1; |
2842 Gear^.X := int2hwFloat(max(LAND_WIDTH,4096) + 2048); |
3220 if (WorldEdge = weWrap) then |
2843 end; |
3221 Gear^.X := int2hwFloat(CalcWorldWrap(Gear^.Target.X - max(384, LAND_WIDTH shr 2), 0)) |
2844 |
3222 else |
2845 Gear^.Y := int2hwFloat(topY-300); |
3223 Gear^.X := int2hwFloat(max(LAND_WIDTH,4096) + 2048); |
3224 end; |
|
3225 |
|
3226 Gear^.Y := int2hwFloat(topY - 300); |
|
3227 |
|
3228 // Appear out of nowhere in wrap |
|
3229 if (WorldEdge = weWrap) then |
|
3230 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBigExplosion); |
|
3231 |
|
2846 Gear^.dX := int2hwFloat(Gear^.Target.X) - int2hwFloat(Gear^.Tag * (Gear^.Health-1) * Gear^.Damage) / 2; |
3232 Gear^.dX := int2hwFloat(Gear^.Target.X) - int2hwFloat(Gear^.Tag * (Gear^.Health-1) * Gear^.Damage) / 2; |
2847 |
3233 |
2848 // calcs for Napalm Strike, so that it will hit the target (without wind at least :P) |
3234 // calcs for Napalm Strike, so that it will hit the target (without wind at least :P) |
2849 if (Gear^.State = 2) then |
3235 if (Gear^.State = 2) then |
2850 Gear^.dX := Gear^.dX - cBombsSpeed * Gear^.Tag * 900 |
3236 Gear^.dX := Gear^.dX - cBombsSpeed * Gear^.Tag * 900 |
2851 // calcs for regular falling gears |
3237 // calcs for regular falling gears |
2852 else if (int2hwFloat(Gear^.Target.Y) - Gear^.Y > _0) then |
3238 else if (int2hwFloat(Gear^.Target.Y) - Gear^.Y > _0) then |
2853 Gear^.dX := Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(Gear^.Target.Y) - Gear^.Y) * 2 / |
3239 Gear^.dX := Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(Gear^.Target.Y) - Gear^.Y) * 2 / |
2854 cGravity) * Gear^.Tag; |
3240 cGravity) * Gear^.Tag; |
2855 |
3241 |
3242 if (WorldEdge = weWrap) then |
|
3243 begin |
|
3244 Gear^.dX := int2hwFloat(CalcWorldWrap(hwRound(Gear^.dX), 0)); |
|
3245 if (((Gear^.Tag = 1) and (not (Gear^.X < Gear^.dX))) or ((Gear^.Tag = -1) and (not (Gear^.X > Gear^.dX)))) then |
|
3246 Gear^.WDTimer:= 1; |
|
3247 end; |
|
3248 |
|
2856 Gear^.doStep := @doStepAirAttackWork; |
3249 Gear^.doStep := @doStepAirAttackWork; |
2857 Gear^.SoundChannel := LoopSound(sndPlane, 4000); |
3250 |
3251 if (WorldEdge = weSea) then |
|
3252 begin |
|
3253 Gear^.SoundChannel := LoopSound(sndPlaneWater, 4000); |
|
3254 Gear^.Karma := 1; |
|
3255 end |
|
3256 else if (WorldEdge = weWrap) then |
|
3257 begin |
|
3258 Gear^.SoundChannel := LoopSound(sndPlane, 500); |
|
3259 Gear^.Karma := 0; |
|
3260 end |
|
3261 else |
|
3262 begin |
|
3263 Gear^.SoundChannel := LoopSound(sndPlane, 4000); |
|
3264 Gear^.Karma := 0; |
|
3265 end; |
|
2858 |
3266 |
2859 end; |
3267 end; |
2860 |
3268 |
2861 //////////////////////////////////////////////////////////////////////////////// |
3269 //////////////////////////////////////////////////////////////////////////////// |
2862 |
3270 |
2865 AllInactive := false; |
3273 AllInactive := false; |
2866 doStepFallingGear(Gear); |
3274 doStepFallingGear(Gear); |
2867 if (Gear^.State and gstCollision) <> 0 then |
3275 if (Gear^.State and gstCollision) <> 0 then |
2868 begin |
3276 begin |
2869 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
3277 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
2870 DeleteGear(Gear); |
|
2871 {$IFNDEF PAS2C} |
3278 {$IFNDEF PAS2C} |
2872 with mobileRecord do |
3279 with mobileRecord do |
2873 if (performRumble <> nil) and (not fastUntilLag) then |
3280 if (performRumble <> nil) and (not fastUntilLag) then |
2874 performRumble(kSystemSoundID_Vibrate); |
3281 performRumble(kSystemSoundID_Vibrate); |
2875 {$ENDIF} |
3282 {$ENDIF} |
3283 DeleteGear(Gear); |
|
2876 exit |
3284 exit |
2877 end; |
3285 end; |
2878 if (GameTicks and $3F) = 0 then |
3286 if (GameTicks and $3F) = 0 then |
2879 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace) |
3287 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace) |
2880 end; |
3288 end; |
2926 end |
3334 end |
2927 else |
3335 else |
2928 begin |
3336 begin |
2929 PlaySound(sndPlaced); |
3337 PlaySound(sndPlaced); |
2930 DeleteGear(Gear); |
3338 DeleteGear(Gear); |
2931 AfterAttack; |
3339 AfterAttack |
2932 end; |
3340 end; |
2933 |
3341 |
2934 HHGear^.State := HHGear^.State and (not (gstAttacking or gstAttacked)); |
3342 HHGear^.State := HHGear^.State and (not (gstAttacking or gstAttacked)); |
2935 HHGear^.Message := HHGear^.Message and (not gmAttack); |
3343 HHGear^.Message := HHGear^.Message and (not gmAttack); |
2936 end; |
3344 end; |
2945 // if not infattack mode wait for hedgehog finish falling to collect cases |
3353 // if not infattack mode wait for hedgehog finish falling to collect cases |
2946 if ((GameFlags and gfInfAttack) <> 0) |
3354 if ((GameFlags and gfInfAttack) <> 0) |
2947 or (HHGear = nil) |
3355 or (HHGear = nil) |
2948 or ((HHGear^.State and gstMoving) = 0) |
3356 or ((HHGear^.State and gstMoving) = 0) |
2949 or (HHGear^.Damage > 0) |
3357 or (HHGear^.Damage > 0) |
2950 or ((HHGear^.State and gstDrowning) = 1) then |
3358 or ((HHGear^.State and gstDrowning) <> 0) then |
2951 begin |
3359 begin |
2952 DeleteGear(Gear); |
3360 DeleteGear(Gear); |
2953 AfterAttack |
3361 AfterAttack |
2954 end |
3362 end |
2955 end; |
3363 end; |
2958 begin |
3366 begin |
2959 if (Gear^.Hedgehog^.Gear = nil) or (Gear^.Hedgehog^.Gear^.Damage > 0) then |
3367 if (Gear^.Hedgehog^.Gear = nil) or (Gear^.Hedgehog^.Gear^.Damage > 0) then |
2960 begin |
3368 begin |
2961 DeleteGear(Gear); |
3369 DeleteGear(Gear); |
2962 AfterAttack; |
3370 AfterAttack; |
3371 exit |
|
2963 end; |
3372 end; |
2964 inc(Gear^.Timer); |
3373 inc(Gear^.Timer); |
2965 if Gear^.Timer = 65 then |
3374 if Gear^.Timer = 65 then |
2966 begin |
3375 begin |
2967 Gear^.Timer := 0; |
3376 Gear^.Timer := 0; |
3054 var |
3463 var |
3055 HHGear: PGear; |
3464 HHGear: PGear; |
3056 hedgehog: PHedgehog; |
3465 hedgehog: PHedgehog; |
3057 State: Longword; |
3466 State: Longword; |
3058 switchDir: Longword; |
3467 switchDir: Longword; |
3468 oldUid: Longword; |
|
3059 begin |
3469 begin |
3060 AllInactive := false; |
3470 AllInactive := false; |
3061 |
3471 |
3062 if ((Gear^.Message and (not (gmSwitch or gmPrecise))) <> 0) or (TurnTimeLeft = 0) then |
3472 if ((Gear^.Message and (not (gmSwitch or gmPrecise))) <> 0) or (TurnTimeLeft = 0) then |
3063 begin |
3473 begin |
3064 hedgehog := Gear^.Hedgehog; |
3474 hedgehog := Gear^.Hedgehog; |
3065 //Msg := Gear^.Message and (not gmSwitch); |
|
3066 DeleteGear(Gear); |
|
3067 ApplyAmmoChanges(hedgehog^); |
3475 ApplyAmmoChanges(hedgehog^); |
3068 |
3476 |
3069 HHGear := CurrentHedgehog^.Gear; |
3477 HHGear := CurrentHedgehog^.Gear; |
3070 ApplyAmmoChanges(HHGear^.Hedgehog^); |
3478 ApplyAmmoChanges(HHGear^.Hedgehog^); |
3071 //HHGear^.Message := Msg; |
3479 DeleteGear(Gear); |
3072 exit |
3480 exit |
3073 end; |
3481 end; |
3074 |
3482 |
3483 HHGear := CurrentHedgehog^.Gear; |
|
3075 if (Gear^.Message and gmSwitch) <> 0 then |
3484 if (Gear^.Message and gmSwitch) <> 0 then |
3076 begin |
3485 begin |
3077 HHGear := CurrentHedgehog^.Gear; |
3486 oldUid:= HHGear^.uid; |
3078 HHGear^.Message := HHGear^.Message and (not gmSwitch); |
3487 HHGear^.Message := HHGear^.Message and (not gmSwitch); |
3079 Gear^.Message := Gear^.Message and (not gmSwitch); |
3488 Gear^.Message := Gear^.Message and (not gmSwitch); |
3080 |
3489 |
3081 // switching in reverse direction |
3490 // switching in reverse direction |
3082 if (Gear^.Message and gmPrecise) <> 0 then |
3491 if (Gear^.Message and gmPrecise) <> 0 then |
3086 end |
3495 end |
3087 else |
3496 else |
3088 switchDir:= 1; |
3497 switchDir:= 1; |
3089 |
3498 |
3090 State := HHGear^.State; |
3499 State := HHGear^.State; |
3091 HHGear^.State := 0; |
3500 if (HHGear^.State and gstMoving) = 0 then |
3501 HHGear^.Active := false; |
|
3502 HHGear^.State := HHGear^.State and gstMoving; |
|
3092 HHGear^.Z := cHHZ; |
3503 HHGear^.Z := cHHZ; |
3093 HHGear^.Active := false; |
|
3094 HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList; |
3504 HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList; |
3095 |
3505 |
3096 PlaySound(sndSwitchHog); |
3506 PlaySound(sndSwitchHog); |
3097 |
3507 |
3098 repeat |
3508 repeat |
3105 |
3515 |
3106 SwitchCurrentHedgehog(@CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]); |
3516 SwitchCurrentHedgehog(@CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]); |
3107 AmmoMenuInvalidated:= true; |
3517 AmmoMenuInvalidated:= true; |
3108 |
3518 |
3109 HHGear := CurrentHedgehog^.Gear; |
3519 HHGear := CurrentHedgehog^.Gear; |
3520 ScriptCall('onHogSwitch', oldUid); |
|
3110 HHGear^.State := State; |
3521 HHGear^.State := State; |
3111 HHGear^.Active := true; |
3522 HHGear^.Active := true; |
3112 FollowGear := HHGear; |
3523 FollowGear := HHGear; |
3113 HHGear^.Z := cCurrHHZ; |
3524 HHGear^.Z := cCurrHHZ; |
3114 // restore precise key |
3525 // restore precise key |
3115 if (switchDir <> 1) then |
3526 if (switchDir <> 1) then |
3116 HHGear^.Message:= HHGear^.Message or gmPrecise; |
3527 HHGear^.Message:= HHGear^.Message or gmPrecise; |
3117 HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList; |
3528 HHGear^.Message:= HHGear^.Message or gmRemoveFromList or gmAddToList; |
3118 Gear^.X := HHGear^.X; |
3529 end; |
3119 Gear^.Y := HHGear^.Y |
3530 doStepHedgehogMoving(HHGear); |
3120 end; |
3531 Gear^.X := HHGear^.X; |
3532 Gear^.Y := HHGear^.Y |
|
3121 end; |
3533 end; |
3122 |
3534 |
3123 procedure doStepSwitcher(Gear: PGear); |
3535 procedure doStepSwitcher(Gear: PGear); |
3124 var |
3536 var |
3125 HHGear: PGear; |
3537 HHGear: PGear; |
3129 HHGear := Gear^.Hedgehog^.Gear; |
3541 HHGear := Gear^.Hedgehog^.Gear; |
3130 OnUsedAmmo(HHGear^.Hedgehog^); |
3542 OnUsedAmmo(HHGear^.Hedgehog^); |
3131 with HHGear^ do |
3543 with HHGear^ do |
3132 begin |
3544 begin |
3133 State := State and (not gstAttacking); |
3545 State := State and (not gstAttacking); |
3134 Message := Message and (not gmAttack) |
3546 Message := Message and (not (gmAttack or gmSwitch)) |
3135 end |
3547 end |
3136 end; |
3548 end; |
3137 |
3549 |
3138 //////////////////////////////////////////////////////////////////////////////// |
3550 //////////////////////////////////////////////////////////////////////////////// |
3139 procedure doStepMortar(Gear: PGear); |
3551 procedure doStepMortar(Gear: PGear); |
3163 |
3575 |
3164 DeleteGear(Gear); |
3576 DeleteGear(Gear); |
3165 exit |
3577 exit |
3166 end; |
3578 end; |
3167 |
3579 |
3580 // particles |
|
3168 if (GameTicks and $3F) = 0 then |
3581 if (GameTicks and $3F) = 0 then |
3169 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
3582 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
3170 end; |
3583 end; |
3171 |
3584 |
3172 //////////////////////////////////////////////////////////////////////////////// |
3585 //////////////////////////////////////////////////////////////////////////////// |
3184 Gear^.AdvBounce:= 1; |
3597 Gear^.AdvBounce:= 1; |
3185 |
3598 |
3186 HHGear := Gear^.Hedgehog^.Gear; |
3599 HHGear := Gear^.Hedgehog^.Gear; |
3187 if HHGear = nil then |
3600 if HHGear = nil then |
3188 begin |
3601 begin |
3602 ClearHitOrder(); |
|
3603 ClearProximityCache(); |
|
3189 DeleteGear(Gear); |
3604 DeleteGear(Gear); |
3190 exit |
3605 exit |
3191 end; |
3606 end; |
3192 |
3607 |
3193 HHGear^.State := HHGear^.State or gstNoDamage; |
3608 HHGear^.State := HHGear^.State or gstNoDamage; |
3215 |
3630 |
3216 // check for drowning |
3631 // check for drowning |
3217 if CheckGearDrowning(HHGear) then |
3632 if CheckGearDrowning(HHGear) then |
3218 begin |
3633 begin |
3219 AfterAttack; |
3634 AfterAttack; |
3635 ClearHitOrder(); |
|
3636 ClearProximityCache(); |
|
3220 DeleteGear(Gear); |
3637 DeleteGear(Gear); |
3221 exit; |
3638 exit; |
3222 end; |
3639 end; |
3223 |
3640 |
3224 inc(Gear^.Damage, 2); |
3641 inc(Gear^.Damage, 2); |
3225 |
|
3226 // if TestCollisionXwithGear(HHGear, hwSign(Gear^.dX)) |
|
3227 // or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY)) then inc(Gear^.Damage, 3); |
|
3228 |
3642 |
3229 dec(i) |
3643 dec(i) |
3230 until (i = 0) |
3644 until (i = 0) |
3231 or (Gear^.Damage > Gear^.Health); |
3645 or (Gear^.Damage > Gear^.Health); |
3232 |
3646 |
3239 Gear^.Pos := 3 |
3653 Gear^.Pos := 3 |
3240 else |
3654 else |
3241 Gear^.Pos := 2; |
3655 Gear^.Pos := 2; |
3242 end; |
3656 end; |
3243 |
3657 |
3244 AmmoShove(Gear, Gear^.Boom, 40); |
3658 AmmoShoveCache(Gear, Gear^.Boom, 40); |
3245 |
3659 |
3246 DrawTunnel(HHGear^.X - HHGear^.dX * 10, |
3660 DrawTunnel(HHGear^.X - HHGear^.dX * 10, |
3247 HHGear^.Y - _2 - HHGear^.dY * 10 + hwAbs(HHGear^.dY) * 2, |
3661 HHGear^.Y - _2 - HHGear^.dY * 10 + hwAbs(HHGear^.dY) * 2, |
3248 HHGear^.dX, |
3662 HHGear^.dX, |
3249 HHGear^.dY, |
3663 HHGear^.dY, |
3250 20 + cHHRadius * 2, |
3664 20 + cHHRadius * 2, |
3251 cHHRadius * 2 + 7); |
3665 cHHRadius * 2 + 7); |
3252 |
3666 |
3253 upd := 0 |
3667 upd := 0 |
3254 end; |
3668 end; |
3669 |
|
3670 inc(Gear^.Timer); |
|
3671 if (Gear^.Timer mod 100) = 0 then |
|
3672 RefillProximityCache(Gear, 300); |
|
3255 |
3673 |
3256 if Gear^.Health < Gear^.Damage then |
3674 if Gear^.Health < Gear^.Damage then |
3257 begin |
3675 begin |
3258 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
3676 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
3259 if hasWishes then |
3677 if hasWishes then |
3273 dy := -dy; |
3691 dy := -dy; |
3274 FrameTicks:= random(400) + 250 |
3692 FrameTicks:= random(400) + 250 |
3275 end |
3693 end |
3276 end; |
3694 end; |
3277 s:= ansistring(Gear^.Hedgehog^.Name); |
3695 s:= ansistring(Gear^.Hedgehog^.Name); |
3278 AddCaption(FormatA(GetEventString(eidKamikaze), s), cWhiteColor, capgrpMessage); |
3696 AddCaption(FormatA(GetEventString(eidKamikaze), s), capcolDefault, capgrpMessage); |
3279 uStats.HedgehogSacrificed(Gear^.Hedgehog); |
3697 uStats.HedgehogSacrificed(Gear^.Hedgehog); |
3280 AfterAttack; |
3698 AfterAttack; |
3281 HHGear^.Message:= HHGear^.Message or gmDestroy; |
3699 HHGear^.Message:= HHGear^.Message or gmDestroy; |
3700 ClearHitOrder(); |
|
3701 ClearProximityCache(); |
|
3282 DeleteGear(Gear); |
3702 DeleteGear(Gear); |
3283 end |
3703 end |
3284 else |
3704 else |
3285 begin |
3705 begin |
3286 dec(Gear^.Health, Gear^.Damage); |
3706 dec(Gear^.Health, Gear^.Damage); |
3287 Gear^.Damage := 0 |
3707 Gear^.Damage := 0 |
3288 end |
3708 end |
3289 end; |
3709 end; |
3290 |
3710 |
3291 procedure doStepKamikazeIdle(Gear: PGear); |
3711 procedure doStepKamikazeIdle(Gear: PGear); |
3712 var HHGear: PGear; |
|
3292 begin |
3713 begin |
3293 AllInactive := false; |
3714 AllInactive := false; |
3294 dec(Gear^.Timer); |
3715 dec(Gear^.Timer); |
3716 HHGear := Gear^.Hedgehog^.Gear; |
|
3717 if (HHGear = nil) or (HHGear^.Damage <> 0) then |
|
3718 begin |
|
3719 if (HHGear <> nil) then |
|
3720 AfterAttack; |
|
3721 ClearHitOrder(); |
|
3722 ClearProximityCache(); |
|
3723 DeleteGear(Gear); |
|
3724 exit; |
|
3725 end; |
|
3295 if Gear^.Timer = 0 then |
3726 if Gear^.Timer = 0 then |
3296 begin |
3727 begin |
3297 Gear^.Pos := 1; |
3728 Gear^.Pos := 1; |
3298 PlaySoundV(sndKamikaze, Gear^.Hedgehog^.Team^.voicepack); |
3729 PlaySoundV(sndKamikaze, Gear^.Hedgehog^.Team^.voicepack); |
3730 ClearHitOrder(); |
|
3731 RefillProximityCache(Gear, 300); |
|
3299 Gear^.doStep := @doStepKamikazeWork |
3732 Gear^.doStep := @doStepKamikazeWork |
3300 end |
3733 end |
3301 end; |
3734 end; |
3302 |
3735 |
3303 procedure doStepKamikaze(Gear: PGear); |
3736 procedure doStepKamikaze(Gear: PGear); |
3359 Gear^.Tag := 0; |
3792 Gear^.Tag := 0; |
3360 |
3793 |
3361 if Gear^.Pos = 0 then |
3794 if Gear^.Pos = 0 then |
3362 begin |
3795 begin |
3363 ///////////// adapted from doMakeExplosion /////////////////////////// |
3796 ///////////// adapted from doMakeExplosion /////////////////////////// |
3364 //fX:= Gear^.X; |
|
3365 //fY:= Gear^.Y; |
|
3366 //fX.QWordValue:= fX.QWordValue and $FFFFFFFF00000000; |
|
3367 //fY.QWordValue:= fY.QWordValue and $FFFFFFFF00000000; |
|
3368 fX:= int2hwFloat(hwRound(Gear^.X)); |
3797 fX:= int2hwFloat(hwRound(Gear^.X)); |
3369 fY:= int2hwFloat(hwRound(Gear^.Y)); |
3798 fY:= int2hwFloat(hwRound(Gear^.Y)); |
3370 dmgBase:= Gear^.Boom shl 1 + cHHRadius div 2; |
3799 dmgBase:= Gear^.Boom shl 1 + cHHRadius div 2; |
3371 partyEpicness:= 0; |
3800 partyEpicness:= 0; |
3372 gi := GearsList; |
3801 gi := GearsList; |
3423 |
3852 |
3424 procedure doStepCakeWalk(Gear: PGear); |
3853 procedure doStepCakeWalk(Gear: PGear); |
3425 var |
3854 var |
3426 tdx, tdy: hwFloat; |
3855 tdx, tdy: hwFloat; |
3427 cakeData: PCakeData; |
3856 cakeData: PCakeData; |
3857 i: Longword; |
|
3428 begin |
3858 begin |
3429 AllInactive := false; |
3859 AllInactive := false; |
3430 |
3860 |
3431 inc(Gear^.Tag); |
3861 inc(Gear^.Tag); |
3432 if Gear^.Tag < 7 then |
3862 if Gear^.Tag < 7 then |
3446 end |
3876 end |
3447 else if Gear^.Timer < 6000 then |
3877 else if Gear^.Timer < 6000 then |
3448 Gear^.RenderTimer:= true; |
3878 Gear^.RenderTimer:= true; |
3449 |
3879 |
3450 if not cakeStep(Gear) then Gear^.doStep:= @doStepCakeFall; |
3880 if not cakeStep(Gear) then Gear^.doStep:= @doStepCakeFall; |
3881 |
|
3882 // Cake passed world edge. |
|
3883 if (Gear^.Karma = 1) then |
|
3884 (* This code is not ideal, but at least not horribly broken. |
|
3885 The cake tries to reach the other side and continue to walk, |
|
3886 but there are some exceptions. |
|
3887 This code is called *after* the X coordinate have been wrapped. |
|
3888 Depending on terrain on the other side, the cake does this: |
|
3889 * Cake collides horizontally (even by 1 pixel): Turn around |
|
3890 * Cake does not see walkable ground above or below: Fall |
|
3891 * Otherwise: Walk normally |
|
3892 *) |
|
3893 begin |
|
3894 // Update coordinates |
|
3895 tdx:=Gear^.X; |
|
3896 if (hwRound(Gear^.X) < leftX) then |
|
3897 Gear^.X:= Gear^.X + int2hwfloat(rightX - leftX) |
|
3898 else Gear^.X:= Gear^.X - int2hwfloat(rightX - leftX); |
|
3899 |
|
3900 Gear^.Tag:= 0; |
|
3901 if ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0)) then |
|
3902 // Cake collided horizontally, turn around. Prevents cake from being stuck in infinite loop. |
|
3903 // This can also happen if the terrain is just a slight slope. :-( |
|
3904 begin |
|
3905 Gear^.X := tdx; |
|
3906 Gear^.Karma := 3; |
|
3907 end |
|
3908 else |
|
3909 begin |
|
3910 // Check if cake has something to walk on the other side. If not, make it drop. |
|
3911 // There is nothing for the cake to stand on. |
|
3912 if (TestCollisionYwithGear(Gear, 1) = 0) and (TestCollisionYwithGear(Gear, -1) = 0) then |
|
3913 Gear^.doStep:= @doStepCakeFall; |
|
3914 Gear^.Karma := 4; |
|
3915 end; |
|
3916 end; |
|
3917 // Cake bounced! |
|
3918 if (Gear^.Karma = 2) or (Gear^.Karma = 3) then |
|
3919 begin |
|
3920 // Turn cake around |
|
3921 Gear^.dX.isNegative := (not Gear^.dX.isNegative); |
|
3922 Gear^.WDTimer := 0; |
|
3923 Gear^.Angle := (LongInt(Gear^.Angle) + 2) and 3; |
|
3924 |
|
3925 // Bounce effect |
|
3926 if (Gear^.Karma = 2) then |
|
3927 AddBounceEffectForGear(Gear, 0.55); |
|
3928 |
|
3929 Gear^.Tag:= 0; |
|
3930 Gear^.Karma := 4; |
|
3931 end; |
|
3932 if (Gear^.Karma = 4) then |
|
3933 begin |
|
3934 // Reset CakePoints to fix cake angle |
|
3935 cakeData:= PCakeData(Gear^.Data); |
|
3936 with cakeData^ do |
|
3937 begin |
|
3938 for i:= 0 to Pred(cakeh) do |
|
3939 begin |
|
3940 CakePoints[i].x := Gear^.X; |
|
3941 CakePoints[i].y := Gear^.Y; |
|
3942 end; |
|
3943 CakeI:= 0; |
|
3944 end; |
|
3945 Gear^.Karma := 0; |
|
3946 end; |
|
3451 |
3947 |
3452 if Gear^.Tag = 0 then |
3948 if Gear^.Tag = 0 then |
3453 begin |
3949 begin |
3454 cakeData:= PCakeData(Gear^.Data); |
3950 cakeData:= PCakeData(Gear^.Data); |
3455 with cakeData^ do |
3951 with cakeData^ do |
3522 |
4018 |
3523 procedure doStepCake(Gear: PGear); |
4019 procedure doStepCake(Gear: PGear); |
3524 begin |
4020 begin |
3525 AllInactive := false; |
4021 AllInactive := false; |
3526 |
4022 |
3527 Gear^.CollisionMask:= lfNotCurrentMask; |
4023 Gear^.CollisionMask:= lfNotCurHogCrate; |
3528 |
4024 |
3529 Gear^.dY:= cMaxWindSpeed * 100; |
4025 Gear^.dY:= cMaxWindSpeed * 100; |
3530 |
4026 |
3531 Gear^.doStep := @doStepCakeFall |
4027 Gear^.doStep := @doStepCakeFall |
3532 end; |
4028 end; |
3533 |
4029 |
3534 //////////////////////////////////////////////////////////////////////////////// |
4030 //////////////////////////////////////////////////////////////////////////////// |
3535 procedure doStepSeductionWork(Gear: PGear); |
4031 procedure doStepSeductionWork(Gear: PGear); |
3536 var i: LongInt; |
4032 var i: LongInt; |
3537 hogs: PGearArrayS; |
4033 hogs: PGearArrayS; |
4034 HHGear: PGear; |
|
3538 begin |
4035 begin |
3539 AllInactive := false; |
4036 AllInactive := false; |
4037 |
|
4038 HHGear := Gear^.Hedgehog^.Gear; |
|
4039 if (HHGear <> nil) and ((HHGear^.State and gstHHDriven) = 0) then |
|
4040 begin |
|
4041 StopSound(sndYoohoo); |
|
4042 AfterAttack; |
|
4043 DeleteGear(Gear); |
|
4044 exit; |
|
4045 end; |
|
4046 |
|
3540 hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius); |
4047 hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius); |
3541 if hogs.size > 0 then |
4048 if hogs.size > 0 then |
3542 begin |
4049 begin |
3543 for i:= 0 to hogs.size - 1 do |
4050 for i:= 0 to hogs.size - 1 do |
3544 with hogs.ar^[i]^ do |
4051 with hogs.ar^[i]^ do |
3554 Active:= true; |
4061 Active:= true; |
3555 end |
4062 end |
3556 else if Hedgehog^.Effects[heFrozen] > 255 then |
4063 else if Hedgehog^.Effects[heFrozen] > 255 then |
3557 Hedgehog^.Effects[heFrozen]:= 255 |
4064 Hedgehog^.Effects[heFrozen]:= 255 |
3558 end ; |
4065 end ; |
4066 AfterAttack; |
|
4067 DeleteGear(Gear); |
|
4068 end; |
|
4069 |
|
4070 procedure doStepSeductionWear(Gear: PGear); |
|
4071 var heart: PVisualGear; |
|
4072 HHGear: PGear; |
|
4073 begin |
|
4074 AllInactive := false; |
|
4075 |
|
4076 HHGear := Gear^.Hedgehog^.Gear; |
|
4077 if (HHGear <> nil) and ((HHGear^.State and gstHHDriven) = 0) then |
|
4078 begin |
|
4079 StopSound(sndYoohoo); |
|
3559 AfterAttack; |
4080 AfterAttack; |
3560 DeleteGear(Gear); |
4081 DeleteGear(Gear); |
3561 (* |
4082 exit; |
3562 Gear^.X := Gear^.X + Gear^.dX; |
4083 end; |
3563 Gear^.Y := Gear^.Y + Gear^.dY; |
4084 |
3564 x := hwRound(Gear^.X); |
|
3565 y := hwRound(Gear^.Y); |
|
3566 |
|
3567 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) then |
|
3568 if (Land[y, x] <> 0) then |
|
3569 begin |
|
3570 Gear^.dX.isNegative := not Gear^.dX.isNegative; |
|
3571 Gear^.dY.isNegative := not Gear^.dY.isNegative; |
|
3572 Gear^.dX := Gear^.dX * _1_5; |
|
3573 Gear^.dY := Gear^.dY * _1_5 - _0_3; |
|
3574 AmmoShove(Gear, 0, 40); |
|
3575 AfterAttack; |
|
3576 DeleteGear(Gear) |
|
3577 end |
|
3578 else |
|
3579 else |
|
3580 begin |
|
3581 AfterAttack; |
|
3582 DeleteGear(Gear) |
|
3583 end*) |
|
3584 end; |
|
3585 |
|
3586 procedure doStepSeductionWear(Gear: PGear); |
|
3587 var heart: PVisualGear; |
|
3588 begin |
|
3589 AllInactive := false; |
|
3590 inc(Gear^.Timer); |
4085 inc(Gear^.Timer); |
3591 if Gear^.Timer > 250 then |
4086 if Gear^.Timer > 250 then |
3592 begin |
4087 begin |
3593 Gear^.Timer := 0; |
4088 Gear^.Timer := 0; |
3594 inc(Gear^.Pos); |
4089 inc(Gear^.Pos); |
3595 if Gear^.Pos = 5 then |
4090 if Gear^.Pos = 5 then |
3596 PlaySound(sndYoohoo); |
4091 PlaySound(sndYoohoo); |
4092 if Gear^.Pos = 14 then |
|
4093 PlaySound(sndKiss); |
|
3597 end; |
4094 end; |
3598 |
4095 |
3599 |
4096 |
3600 // note: use GameTicks, not RealTicks, otherwise amount can vary greatly |
4097 // note: use GameTicks, not RealTicks, otherwise amount can vary greatly |
3601 if (Gear^.Pos = 14) and (GameTicks and $1 = 0) then |
4098 if (Gear^.Pos = 14) and (GameTicks and $1 = 0) then |
3602 begin |
4099 begin |
3603 heart:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot); |
4100 heart:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot); |
3604 if heart <> nil then |
4101 if heart <> nil then |
3605 with heart^ do |
4102 with heart^ do |
3606 begin |
4103 begin |
3607 { // old calcs |
|
3608 dx:= 0.001 * (random(200)); |
|
3609 dy:= 0.001 * (random(200)); |
|
3610 if random(2) = 0 then |
|
3611 dx := -dx; |
|
3612 if random(2) = 0 then |
|
3613 dy := -dy; |
|
3614 } |
|
3615 |
4104 |
3616 // randomize speed in both directions |
4105 // randomize speed in both directions |
3617 dx:= 0.001 * (random(201)); |
4106 dx:= 0.001 * (random(201)); |
3618 dy:= 0.001 * (random(201)); |
4107 dy:= 0.001 * (random(201)); |
3619 |
4108 |
3647 end; |
4136 end; |
3648 |
4137 |
3649 procedure doStepSeduction(Gear: PGear); |
4138 procedure doStepSeduction(Gear: PGear); |
3650 begin |
4139 begin |
3651 AllInactive := false; |
4140 AllInactive := false; |
3652 //DeleteCI(Gear^.Hedgehog^.Gear); |
|
3653 Gear^.doStep := @doStepSeductionWear |
4141 Gear^.doStep := @doStepSeductionWear |
3654 end; |
4142 end; |
3655 |
4143 |
3656 //////////////////////////////////////////////////////////////////////////////// |
4144 //////////////////////////////////////////////////////////////////////////////// |
3657 procedure doStepWaterUp(Gear: PGear); |
4145 procedure doStepWaterUp(Gear: PGear); |
3700 procedure doStepDrillDrilling(Gear: PGear); |
4188 procedure doStepDrillDrilling(Gear: PGear); |
3701 var |
4189 var |
3702 t: PGearArray; |
4190 t: PGearArray; |
3703 tempColl: Word; |
4191 tempColl: Word; |
3704 begin |
4192 begin |
4193 WorldWrap(Gear); |
|
3705 AllInactive := false; |
4194 AllInactive := false; |
3706 if (Gear^.Timer > 0) and (Gear^.Timer mod 10 <> 0) then |
4195 if (Gear^.Timer > 0) and (Gear^.Timer mod 10 <> 0) then |
3707 begin |
4196 begin |
3708 dec(Gear^.Timer); |
4197 dec(Gear^.Timer); |
3709 exit; |
4198 exit; |
3719 StopSoundChan(Gear^.SoundChannel); |
4208 StopSoundChan(Gear^.SoundChannel); |
3720 exit |
4209 exit |
3721 end; |
4210 end; |
3722 |
4211 |
3723 tempColl:= Gear^.CollisionMask; |
4212 tempColl:= Gear^.CollisionMask; |
3724 Gear^.CollisionMask:= $007F; |
4213 Gear^.CollisionMask:= lfObjMask; |
3725 if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) <> 0) or (TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) <> 0) or (GameTicks > Gear^.FlightTime) then |
4214 if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) <> 0) or (TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) <> 0) or (GameTicks > Gear^.FlightTime) then |
3726 t := CheckGearsCollision(Gear) |
4215 t := CheckGearsCollision(Gear) |
3727 else t := nil; |
4216 else t := nil; |
3728 Gear^.CollisionMask:= tempColl; |
4217 Gear^.CollisionMask:= tempColl; |
3729 //fixes drill not exploding when touching HH bug |
4218 //fixes drill not exploding when touching HH bug |
3801 end; |
4290 end; |
3802 |
4291 |
3803 Gear^.X:= Gear^.X+Gear^.dX*4; |
4292 Gear^.X:= Gear^.X+Gear^.dX*4; |
3804 Gear^.Y:= Gear^.Y+Gear^.dY*4; |
4293 Gear^.Y:= Gear^.Y+Gear^.dY*4; |
3805 Gear^.SoundChannel := LoopSound(sndDrillRocket); |
4294 Gear^.SoundChannel := LoopSound(sndDrillRocket); |
4295 Gear^.Pos:= 1; |
|
3806 Gear^.doStep := @doStepDrillDrilling; |
4296 Gear^.doStep := @doStepDrillDrilling; |
3807 |
4297 |
3808 if (Gear^.State and gsttmpFlag) <> 0 then |
4298 if (Gear^.State and gsttmpFlag) <> 0 then |
3809 gear^.RenderTimer:= true; |
4299 gear^.RenderTimer:= true; |
3810 if Gear^.Timer > 0 then dec(Gear^.Timer) |
4300 if Gear^.Timer > 0 then dec(Gear^.Timer) |
3843 begin |
4333 begin |
3844 rx := rndSign(getRandomf * _0_1); |
4334 rx := rndSign(getRandomf * _0_1); |
3845 ry := rndSign(getRandomf * _0_1); |
4335 ry := rndSign(getRandomf * _0_1); |
3846 |
4336 |
3847 ball:= AddGear(gx, gy, gtBall, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0); |
4337 ball:= AddGear(gx, gy, gtBall, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0); |
3848 ball^.CollisionMask:= lfNotCurrentMask; |
4338 ball^.CollisionMask:= lfNotCurHogCrate; |
3849 |
4339 |
3850 PlaySound(sndGun); |
4340 PlaySound(sndGun); |
3851 end; |
4341 end; |
3852 |
4342 |
3853 if (Gear^.Timer = 0) or ((HHGear^.State and gstHHDriven) = 0) then |
4343 if (Gear^.Timer = 0) or ((HHGear^.State and gstHHDriven) = 0) then |
3962 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY * |
4452 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY * |
3963 _0_5, 0); |
4453 _0_5, 0); |
3964 dec(Gear^.Health) |
4454 dec(Gear^.Health) |
3965 end; |
4455 end; |
3966 s:= ansistring(inttostr(Gear^.Health)); |
4456 s:= ansistring(inttostr(Gear^.Health)); |
3967 AddCaption(formatA(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate); |
4457 AddCaption(formatA(trmsg[sidRemaining], s), capcolDefault, capgrpAmmostate); |
3968 end; |
4458 end; |
3969 |
4459 |
3970 if (HHGear <> nil) and ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then |
4460 if (HHGear <> nil) and ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then |
3971 begin |
4461 begin |
3972 Gear^.State := Gear^.State or gsttmpFlag; |
4462 Gear^.State := Gear^.State or gsttmpFlag; |
3973 PauseMusic; |
4463 PlayMusicSound(sndRideOfTheValkyries); |
3974 playSound(sndRideOfTheValkyries); |
|
3975 inCinematicMode:= true; |
4464 inCinematicMode:= true; |
3976 end; |
4465 end; |
3977 |
4466 |
3978 // pickup bonuses |
4467 // pickup bonuses |
3979 t := CheckGearNear(Gear, gtCase, 36, 36); |
4468 t := CheckGearNear(Gear, gtCase, 36, 36); |
3984 |
4473 |
3985 if ((Gear^.State and gstCollision) <> 0) or CheckGearDrowning(Gear) then |
4474 if ((Gear^.State and gstCollision) <> 0) or CheckGearDrowning(Gear) then |
3986 begin |
4475 begin |
3987 inCinematicMode:= false; |
4476 inCinematicMode:= false; |
3988 StopSoundChan(Gear^.SoundChannel); |
4477 StopSoundChan(Gear^.SoundChannel); |
3989 StopSound(sndRideOfTheValkyries); |
4478 StopMusicSound(sndRideOfTheValkyries); |
3990 ResumeMusic; |
|
3991 |
4479 |
3992 if ((Gear^.State and gstCollision) <> 0) then |
4480 if ((Gear^.State and gstCollision) <> 0) then |
3993 begin |
4481 begin |
3994 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
4482 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
3995 for i:= 0 to 15 do |
4483 for i:= 0 to 15 do |
4048 isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); |
4536 isUnderwater:= CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + Gear^.Radius); |
4049 if Gear^.Pos > 0 then |
4537 if Gear^.Pos > 0 then |
4050 dec(Gear^.Pos); |
4538 dec(Gear^.Pos); |
4051 AllInactive := false; |
4539 AllInactive := false; |
4052 HHGear := Gear^.Hedgehog^.Gear; |
4540 HHGear := Gear^.Hedgehog^.Gear; |
4053 //dec(Gear^.Timer); |
|
4054 move := _0_2; |
4541 move := _0_2; |
4055 fuel := 50; |
4542 fuel := 50; |
4056 (*if (HHGear^.Message and gmPrecise) <> 0 then |
|
4057 begin |
|
4058 move:= _0_02; |
|
4059 fuel:= 5; |
|
4060 end;*) |
|
4061 if HHGear^.Message and gmPrecise <> 0 then |
4543 if HHGear^.Message and gmPrecise <> 0 then |
4062 HedgehogChAngle(HHGear) |
4544 HedgehogChAngle(HHGear) |
4063 else if Gear^.Health > 0 then |
4545 else if (Gear^.Health > 0) or (Gear^.Health = JETPACK_FUEL_INFINITE) then |
4064 begin |
4546 begin |
4065 if HHGear^.Message and gmUp <> 0 then |
4547 if HHGear^.Message and gmUp <> 0 then |
4066 begin |
4548 begin |
4067 if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then |
4549 if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then |
4068 begin |
4550 begin |
4080 begin |
4562 begin |
4081 PlaySound(sndJetpackBoost); |
4563 PlaySound(sndJetpackBoost); |
4082 HHGear^.dY := HHGear^.dY - move; |
4564 HHGear^.dY := HHGear^.dY - move; |
4083 end |
4565 end |
4084 end; |
4566 end; |
4085 dec(Gear^.Health, fuel); |
4567 if Gear^.Health <> JETPACK_FUEL_INFINITE then |
4568 dec(Gear^.Health, fuel); |
|
4086 Gear^.MsgParam := Gear^.MsgParam or gmUp; |
4569 Gear^.MsgParam := Gear^.MsgParam or gmUp; |
4087 Gear^.Timer := GameTicks |
4570 Gear^.Timer := GameTicks |
4088 end; |
4571 end; |
4089 move.isNegative := (HHGear^.Message and gmLeft) <> 0; |
4572 move.isNegative := (HHGear^.Message and gmLeft) <> 0; |
4090 if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then |
4573 if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then |
4106 else bubble^.X := bubble^.X - 28; |
4589 else bubble^.X := bubble^.X - 28; |
4107 end; |
4590 end; |
4108 end |
4591 end |
4109 end |
4592 end |
4110 else PlaySound(sndJetpackBoost); |
4593 else PlaySound(sndJetpackBoost); |
4111 dec(Gear^.Health, fuel div 5); |
4594 if Gear^.Health <> JETPACK_FUEL_INFINITE then |
4595 dec(Gear^.Health, fuel div 5); |
|
4112 Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight)); |
4596 Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight)); |
4113 Gear^.Timer := GameTicks |
4597 Gear^.Timer := GameTicks |
4114 end |
4598 end |
4115 end; |
4599 end; |
4116 |
4600 |
4119 begin |
4603 begin |
4120 Gear^.Timer := 0; |
4604 Gear^.Timer := 0; |
4121 Gear^.MsgParam := 0 |
4605 Gear^.MsgParam := 0 |
4122 end; |
4606 end; |
4123 |
4607 |
4124 if Gear^.Health < 0 then |
4608 if (Gear^.Health < 0) and (Gear^.Health <> JETPACK_FUEL_INFINITE) then |
4125 Gear^.Health := 0; |
4609 Gear^.Health := 0; |
4126 |
4610 |
4127 i:= Gear^.Health div 20; |
4611 i:= Gear^.Health div 20; |
4128 |
4612 |
4129 if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
4613 if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
4130 begin |
4614 begin |
4131 Gear^.Damage:= i; |
4615 Gear^.Damage:= i; |
4132 //AddCaption('Fuel: '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate); |
|
4133 FreeAndNilTexture(Gear^.Tex); |
4616 FreeAndNilTexture(Gear^.Tex); |
4134 Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(i) + '%'), cWhiteColor, fntSmall) |
4617 if Gear^.Health <> JETPACK_FUEL_INFINITE then |
4618 Gear^.Tex := RenderStringTex(FormatA(trmsg[sidFuel], ansistring(inttostr(i))), cWhiteColor, fntSmall) |
|
4135 end; |
4619 end; |
4136 |
4620 |
4137 if (HHGear^.Message and (gmAttack or gmUp or gmLeft or gmRight) <> 0) and |
4621 if (HHGear^.Message and (gmAttack or gmUp or gmLeft or gmRight) <> 0) and |
4138 (HHGear^.Message and gmPrecise = 0) then |
4622 (HHGear^.Message and gmPrecise = 0) then |
4139 Gear^.State := Gear^.State and (not gsttmpFlag); |
4623 Gear^.State := Gear^.State and (not gsttmpFlag); |
4151 |
4635 |
4152 if ((Gear^.State and gsttmpFlag) = 0) |
4636 if ((Gear^.State and gsttmpFlag) = 0) |
4153 or (HHGear^.dY < _0) then |
4637 or (HHGear^.dY < _0) then |
4154 doStepHedgehogMoving(HHGear); |
4638 doStepHedgehogMoving(HHGear); |
4155 |
4639 |
4156 if // (Gear^.Health = 0) |
4640 if |
4157 (HHGear^.Damage <> 0) |
4641 (HHGear^.Damage <> 0) |
4158 //or CheckGearDrowning(HHGear) |
|
4159 // drown if too deep under water |
4642 // drown if too deep under water |
4160 or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y)) |
4643 or (cWaterLine + cVisibleWater * 4 < hwRound(HHGear^.Y)) |
4161 or (TurnTimeLeft = 0) |
4644 or (TurnTimeLeft = 0) |
4162 // allow brief ground touches - to be fair on this, might need another counter |
4645 // allow brief ground touches - to be fair on this, might need another counter |
4163 or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0)) |
4646 or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0)) |
4167 begin |
4650 begin |
4168 Message := 0; |
4651 Message := 0; |
4169 Active := true; |
4652 Active := true; |
4170 State := State or gstMoving |
4653 State := State or gstMoving |
4171 end; |
4654 end; |
4172 DeleteGear(Gear); |
4655 if (GetAmmoEntry(HHGear^.Hedgehog^, amJetpack)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) and (HHGear^.Hedgehog^.MultiShootAttacks = 0) then |
4173 if (GetAmmoEntry(HHGear^.Hedgehog^, amJetpack)^.Count >= 1) and ((Ammoz[HHGear^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then |
|
4174 HHGear^.Hedgehog^.CurAmmoType:= amJetpack; |
4656 HHGear^.Hedgehog^.CurAmmoType:= amJetpack; |
4175 isCursorVisible := false; |
4657 isCursorVisible := false; |
4176 ApplyAmmoChanges(HHGear^.Hedgehog^); |
4658 ApplyAmmoChanges(HHGear^.Hedgehog^); |
4177 // if Gear^.Tex <> nil then FreeTexture(Gear^.Tex); |
4659 DeleteGear(Gear); |
4178 |
|
4179 // Gear^.Tex:= RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(round(Gear^.Health / 20)) + '%', cWhiteColor, fntSmall) |
|
4180 |
|
4181 //AddCaption(trmsg[sidFuel]+': '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate); |
|
4182 end |
4660 end |
4183 end; |
4661 end; |
4184 |
4662 |
4185 procedure doStepJetpack(Gear: PGear); |
4663 procedure doStepJetpack(Gear: PGear); |
4186 var |
4664 var |
4214 AllInactive := false; |
4692 AllInactive := false; |
4215 Gear^.Pos := 0; |
4693 Gear^.Pos := 0; |
4216 if Gear^.Timer < 2000 then |
4694 if Gear^.Timer < 2000 then |
4217 inc(Gear^.Timer, 1) |
4695 inc(Gear^.Timer, 1) |
4218 else |
4696 else |
4219 begin |
4697 DeleteGear(Gear) |
4220 DeleteGear(Gear); |
|
4221 end; |
|
4222 end; |
4698 end; |
4223 |
4699 |
4224 procedure doStepBirdyFly(Gear: PGear); |
4700 procedure doStepBirdyFly(Gear: PGear); |
4225 var |
4701 var |
4226 HHGear: PGear; |
4702 HHGear: PGear; |
4227 fuel, i: LongInt; |
4703 energy, i: LongInt; |
4228 move: hwFloat; |
4704 move: hwFloat; |
4229 s: ansistring; |
4705 s: ansistring; |
4230 begin |
4706 begin |
4231 HHGear := Gear^.Hedgehog^.Gear; |
4707 HHGear := Gear^.Hedgehog^.Gear; |
4232 if HHGear = nil then |
4708 if HHGear = nil then |
4240 AfterAttack; |
4716 AfterAttack; |
4241 exit |
4717 exit |
4242 end; |
4718 end; |
4243 |
4719 |
4244 move := _0_2; |
4720 move := _0_2; |
4245 fuel := 50; |
4721 energy:= 50; |
4246 |
4722 |
4247 if Gear^.Pos > 0 then |
4723 if Gear^.Pos > 0 then |
4248 dec(Gear^.Pos, 1) |
4724 dec(Gear^.Pos, 1) |
4249 else if (HHGear^.Message and (gmLeft or gmRight or gmUp)) <> 0 then |
4725 else if (HHGear^.Message and (gmLeft or gmRight or gmUp)) <> 0 then |
4250 Gear^.Pos := 500; |
4726 Gear^.Pos := 500; |
4258 begin |
4734 begin |
4259 if (not HHGear^.dY.isNegative) |
4735 if (not HHGear^.dY.isNegative) |
4260 or (HHGear^.Y > -_256) then |
4736 or (HHGear^.Y > -_256) then |
4261 HHGear^.dY := HHGear^.dY - move; |
4737 HHGear^.dY := HHGear^.dY - move; |
4262 |
4738 |
4263 dec(Gear^.Health, fuel); |
4739 if (Gear^.Health <> BIRDY_ENERGY_INFINITE) then |
4740 dec(Gear^.Health, energy); |
|
4264 Gear^.MsgParam := Gear^.MsgParam or gmUp; |
4741 Gear^.MsgParam := Gear^.MsgParam or gmUp; |
4265 end; |
4742 end; |
4266 |
4743 |
4267 if (HHGear^.Message and gmLeft) <> 0 then move.isNegative := true; |
4744 if (HHGear^.Message and gmLeft) <> 0 then move.isNegative := true; |
4268 if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then |
4745 if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then |
4269 begin |
4746 begin |
4270 HHGear^.dX := HHGear^.dX + (move * _0_1); |
4747 HHGear^.dX := HHGear^.dX + (move * _0_1); |
4271 dec(Gear^.Health, fuel div 5); |
4748 if (Gear^.Health <> BIRDY_ENERGY_INFINITE) then |
4749 dec(Gear^.Health, energy div 5); |
|
4272 Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight)); |
4750 Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight)); |
4273 end; |
4751 end; |
4274 |
4752 |
4275 if Gear^.Health < 0 then |
4753 if (Gear^.Health < 0) and (Gear^.Health <> BIRDY_ENERGY_INFINITE) then |
4276 Gear^.Health := 0; |
4754 Gear^.Health := 0; |
4277 |
4755 |
4278 if ((GameTicks and $FF) = 0) and (Gear^.Health < 500) then |
4756 if ((GameTicks and $FF) = 0) and (Gear^.Health < 500) and (Gear^.Health <> BIRDY_ENERGY_INFINITE) then |
4279 for i:= ((500-Gear^.Health) div 250) downto 0 do |
4757 for i:= ((500-Gear^.Health) div 250) downto 0 do |
4280 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFeather); |
4758 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFeather); |
4281 |
4759 |
4282 if (HHGear^.Message and gmAttack <> 0) then |
4760 if (HHGear^.Message and gmAttack <> 0) then |
4283 begin |
4761 begin |
4287 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + 32, gtEgg, 0, Gear^.dX * _0_5, Gear^.dY, 0); |
4765 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + 32, gtEgg, 0, Gear^.dX * _0_5, Gear^.dY, 0); |
4288 PlaySound(sndBirdyLay); |
4766 PlaySound(sndBirdyLay); |
4289 dec(Gear^.FlightTime) |
4767 dec(Gear^.FlightTime) |
4290 end; |
4768 end; |
4291 s:= ansistring(inttostr(Gear^.FlightTime)); |
4769 s:= ansistring(inttostr(Gear^.FlightTime)); |
4292 AddCaption(formatA(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate); |
4770 AddCaption(formatA(trmsg[sidRemaining], s), capcolDefault, capgrpAmmostate); |
4293 end; |
4771 end; |
4294 |
4772 |
4295 if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then |
4773 if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then |
4296 Gear^.State := Gear^.State and (not gsttmpFlag); |
4774 Gear^.State := Gear^.State and (not gsttmpFlag); |
4297 |
4775 |
4347 if (HHGear = nil) or ((HHGear^.State and gstHHDriven) = 0) then |
4825 if (HHGear = nil) or ((HHGear^.State and gstHHDriven) = 0) then |
4348 begin |
4826 begin |
4349 Gear^.Hedgehog := nil; |
4827 Gear^.Hedgehog := nil; |
4350 Gear^.Timer := 0; |
4828 Gear^.Timer := 0; |
4351 Gear^.State := Gear^.State or gstAnimation or gstTmpFlag; |
4829 Gear^.State := Gear^.State or gstAnimation or gstTmpFlag; |
4352 Gear^.Timer := 0; |
|
4353 Gear^.doStep := @doStepBirdyDisappear; |
4830 Gear^.doStep := @doStepBirdyDisappear; |
4354 CurAmmoGear := nil; |
4831 CurAmmoGear := nil; |
4355 isCursorVisible := false; |
4832 isCursorVisible := false; |
4356 AfterAttack; |
4833 AfterAttack; |
4357 exit |
4834 exit |
4421 i: LongInt; |
4898 i: LongInt; |
4422 begin |
4899 begin |
4423 AllInactive := false; |
4900 AllInactive := false; |
4424 Gear^.dX := Gear^.dX; |
4901 Gear^.dX := Gear^.dX; |
4425 doStepFallingGear(Gear); |
4902 doStepFallingGear(Gear); |
4426 // CheckGearDrowning(Gear); // already checked for in doStepFallingGear |
|
4427 CalcRotationDirAngle(Gear); |
4903 CalcRotationDirAngle(Gear); |
4428 |
4904 |
4429 if (Gear^.State and gstCollision) <> 0 then |
4905 if (Gear^.State and gstCollision) <> 0 then |
4430 begin |
4906 begin |
4431 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLPoisoned, $C0E0FFE0); |
4907 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLPoisoned, $C0E0FFE0); |
4450 |
4926 |
4451 //////////////////////////////////////////////////////////////////////////////// |
4927 //////////////////////////////////////////////////////////////////////////////// |
4452 procedure doPortalColorSwitch(); |
4928 procedure doPortalColorSwitch(); |
4453 var CurWeapon: PAmmo; |
4929 var CurWeapon: PAmmo; |
4454 begin |
4930 begin |
4455 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then |
4931 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and ((CurrentHedgehog^.Gear^.State and gstHHDriven) <> 0) and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then |
4456 with CurrentHedgehog^ do |
4932 with CurrentHedgehog^ do |
4457 if (CurAmmoType = amPortalGun) then |
4933 if (CurAmmoType = amPortalGun) then |
4458 begin |
4934 begin |
4459 PlaySound(sndPortalSwitch); |
4935 PlaySound(sndPortalSwitch); |
4460 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSwitch); |
4936 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSwitch); |
4568 continue; |
5044 continue; |
4569 end |
5045 end |
4570 else |
5046 else |
4571 if not ((Gear^.dX*ox + Gear^.dY*oy).isNegative) then |
5047 if not ((Gear^.dX*ox + Gear^.dY*oy).isNegative) then |
4572 continue; |
5048 continue; |
4573 |
|
4574 if iterator^.Kind = gtDuck then |
|
4575 // Make duck go into “falling” mode again |
|
4576 iterator^.Pos:= 0; |
|
4577 |
5049 |
4578 isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot, gtMinigunBullet]); |
5050 isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot, gtMinigunBullet]); |
4579 |
5051 |
4580 r:= int2hwFloat(iterator^.Radius); |
5052 r:= int2hwFloat(iterator^.Radius); |
4581 |
5053 |
4755 iterator^.dX := resetdx; |
5227 iterator^.dX := resetdx; |
4756 iterator^.dY := resetdy; |
5228 iterator^.dY := resetdy; |
4757 continue; |
5229 continue; |
4758 end; |
5230 end; |
4759 end; |
5231 end; |
5232 |
|
5233 if iterator^.Kind = gtKamikaze then |
|
5234 RefillProximityCache(iterator, 300); |
|
4760 |
5235 |
4761 // |
5236 // |
4762 // You're now officially portaled! |
5237 // You're now officially portaled! |
4763 // |
5238 // |
4764 |
5239 |
4977 newPortal^.State := newPortal^.State and (not gstCollision); |
5452 newPortal^.State := newPortal^.State and (not gstCollision); |
4978 newPortal^.State := newPortal^.State or gstMoving; |
5453 newPortal^.State := newPortal^.State or gstMoving; |
4979 newPortal^.doStep := @doStepMovingPortal; |
5454 newPortal^.doStep := @doStepMovingPortal; |
4980 end; |
5455 end; |
4981 |
5456 |
5457 procedure doStepPiano(Gear: PGear); |
|
5458 var valid: boolean; |
|
5459 HHGear: PGear; |
|
5460 begin |
|
5461 AllInactive := false; |
|
5462 valid := true; |
|
5463 |
|
5464 if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then |
|
5465 HHGear := Gear^.Hedgehog^.Gear; |
|
5466 |
|
5467 if (WorldEdge = weBounce) then |
|
5468 if (hwRound(Gear^.X) - Gear^.Radius < leftX) then |
|
5469 valid := false |
|
5470 else if (hwRound(Gear^.X) + Gear^.Radius > rightX) then |
|
5471 valid := false; |
|
5472 |
|
5473 if (not valid) then |
|
5474 begin |
|
5475 if (HHGear <> nil) then |
|
5476 begin |
|
5477 HHGear^.Message := HHGear^.Message and (not gmAttack); |
|
5478 HHGear^.State := HHGear^.State and (not gstAttacking); |
|
5479 HHGear^.State := HHGear^.State or gstChooseTarget; |
|
5480 isCursorVisible := true; |
|
5481 end; |
|
5482 DeleteGear(Gear); |
|
5483 PlaySound(sndDenied); |
|
5484 exit; |
|
5485 end; |
|
5486 |
|
5487 isCursorVisible := false; |
|
5488 if (HHGear <> nil) then |
|
5489 begin |
|
5490 PlaySoundV(sndIncoming, Gear^.Hedgehog^.Team^.voicepack); |
|
5491 // Tuck the hedgehog away until the piano attack is completed |
|
5492 Gear^.Hedgehog^.Unplaced:= true; |
|
5493 HHGear^.X:= _0; |
|
5494 HHGear^.Y:= _0; |
|
5495 end; |
|
5496 |
|
5497 PauseMusic; |
|
5498 Gear^.doStep:= @doStepPianoWork; |
|
5499 end; |
|
4982 //////////////////////////////////////////////////////////////////////////////// |
5500 //////////////////////////////////////////////////////////////////////////////// |
4983 procedure doStepPiano(Gear: PGear); |
5501 procedure doStepPianoWork(Gear: PGear); |
4984 var |
5502 var |
4985 r0, r1: LongInt; |
5503 r0, r1: LongInt; |
4986 odY: hwFloat; |
5504 odY: hwFloat; |
4987 begin |
5505 begin |
4988 AllInactive := false; |
5506 AllInactive := false; |
5507 // Play piano notes with slot keys |
|
4989 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and |
5508 if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and |
4990 ((CurrentHedgehog^.Gear^.Message and gmSlot) <> 0) then |
5509 ((CurrentHedgehog^.Gear^.Message and gmSlot) <> 0) then |
4991 begin |
5510 begin |
5511 // Piano notes are played if sound OR music (or both) is enabled |
|
4992 case CurrentHedgehog^.Gear^.MsgParam of |
5512 case CurrentHedgehog^.Gear^.MsgParam of |
4993 0: PlaySound(sndPiano0); |
5513 0: PlaySound(sndPiano0, false, false, true); |
4994 1: PlaySound(sndPiano1); |
5514 1: PlaySound(sndPiano1, false, false, true); |
4995 2: PlaySound(sndPiano2); |
5515 2: PlaySound(sndPiano2, false, false, true); |
4996 3: PlaySound(sndPiano3); |
5516 3: PlaySound(sndPiano3, false, false, true); |
4997 4: PlaySound(sndPiano4); |
5517 4: PlaySound(sndPiano4, false, false, true); |
4998 5: PlaySound(sndPiano5); |
5518 5: PlaySound(sndPiano5, false, false, true); |
4999 6: PlaySound(sndPiano6); |
5519 6: PlaySound(sndPiano6, false, false, true); |
5000 7: PlaySound(sndPiano7); |
5520 7: PlaySound(sndPiano7, false, false, true); |
5001 else PlaySound(sndPiano8); |
5521 8: PlaySound(sndPiano8, false, false, true); |
5002 end; |
5522 end; |
5003 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote); |
5523 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote); |
5004 CurrentHedgehog^.Gear^.MsgParam := 0; |
5524 CurrentHedgehog^.Gear^.MsgParam := 0; |
5005 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSlot); |
5525 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSlot); |
5006 end; |
5526 end; |
5007 |
5527 |
5008 if (*((Gear^.Pos = 3) and ((GameFlags and gfSolidLand) <> 0)) or*) (Gear^.Pos = 5) then |
5528 if (Gear^.Pos = 5) then |
5009 begin |
5529 begin |
5010 Gear^.dY := Gear^.dY + cGravity * 2; |
5530 Gear^.dY := Gear^.dY + cGravity * 2; |
5011 Gear^.Y := Gear^.Y + Gear^.dY; |
5531 Gear^.Y := Gear^.Y + Gear^.dY; |
5012 if CheckGearDrowning(Gear) then |
5532 if CheckGearDrowning(Gear) then |
5013 begin |
5533 begin |
5119 x := hwRound(Gear^.X); |
5639 x := hwRound(Gear^.X); |
5120 y := hwRound(Gear^.Y); |
5640 y := hwRound(Gear^.Y); |
5121 |
5641 |
5122 if WorldEdge = weWrap then |
5642 if WorldEdge = weWrap then |
5123 begin |
5643 begin |
5124 if x > LongInt(rightX) then |
5644 if x > rightX then |
5125 repeat |
5645 repeat |
5126 dec(x, playWidth); |
5646 dec(x, playWidth); |
5127 dec(rx, playWidth); |
5647 dec(rx, playWidth); |
5128 until x <= LongInt(rightX) |
5648 until x <= rightX |
5129 else if x < LongInt(leftX) then |
5649 else if x < leftX then |
5130 repeat |
5650 repeat |
5131 inc(x, playWidth); |
5651 inc(x, playWidth); |
5132 inc(rx, playWidth); |
5652 inc(rx, playWidth); |
5133 until x >= LongInt(leftX); |
5653 until x >= leftX; |
5134 end |
5654 end |
5135 else if (WorldEdge = weBounce) then |
5655 else if (WorldEdge = weBounce) then |
5136 begin |
5656 begin |
5137 if (not justBounced) and ((x > LongInt(rightX)) or (x < LongInt(leftX))) then |
5657 if (not justBounced) and ((x > rightX) or (x < leftX)) then |
5138 begin |
5658 begin |
5139 // reflect |
5659 // reflect |
5140 lX:= lX - ldX + ((oX - lX) * 2); |
5660 lX:= lX - ldX + ((oX - lX) * 2); |
5141 lY:= lY - ldY; |
5661 lY:= lY - ldY; |
5142 Gear^.X:= oX; |
5662 Gear^.X:= oX; |
5185 // if at least 5 collisions occured |
5705 // if at least 5 collisions occured |
5186 if Gear^.Damage > 0 then |
5706 if Gear^.Damage > 0 then |
5187 begin |
5707 begin |
5188 if ((GameFlags and gfSolidLand) = 0) then |
5708 if ((GameFlags and gfSolidLand) = 0) then |
5189 begin |
5709 begin |
5190 DrawExplosion(rX,rY,Gear^.Radius); |
5710 doMakeExplosion(rX,rY,Gear^.Radius, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx); |
5191 end; |
5711 end; |
5192 |
5712 |
5193 // kick nearby hogs |
5713 // kick nearby hogs |
5194 AmmoShove(Gear, Gear^.Boom, 50); |
5714 AmmoShove(Gear, Gear^.Boom, 50); |
5195 |
5715 |
5267 // push the shooting Hedgehog back |
5787 // push the shooting Hedgehog back |
5268 Gear^.dX.isNegative := not Gear^.dX.isNegative; |
5788 Gear^.dX.isNegative := not Gear^.dX.isNegative; |
5269 Gear^.dY.isNegative := not Gear^.dY.isNegative; |
5789 Gear^.dY.isNegative := not Gear^.dY.isNegative; |
5270 HHGear^.dX := Gear^.dX; |
5790 HHGear^.dX := Gear^.dX; |
5271 HHGear^.dY := Gear^.dY; |
5791 HHGear^.dY := Gear^.dY; |
5272 AmmoShove(Gear, 0, 80); |
5792 AmmoShove(Gear, 0, 79); |
5273 Gear^.dX.isNegative := not Gear^.dX.isNegative; |
5793 Gear^.dX.isNegative := not Gear^.dX.isNegative; |
5274 Gear^.dY.isNegative := not Gear^.dY.isNegative; |
5794 Gear^.dY.isNegative := not Gear^.dY.isNegative; |
5275 end; |
5795 end; |
5276 |
5796 |
5277 Gear^.doStep := @doStepSineGunShotWork; |
5797 Gear^.doStep := @doStepSineGunShotWork; |
5291 begin |
5811 begin |
5292 AllInactive := false; |
5812 AllInactive := false; |
5293 HHGear := Gear^.Hedgehog^.Gear; |
5813 HHGear := Gear^.Hedgehog^.Gear; |
5294 if HHGear = nil then |
5814 if HHGear = nil then |
5295 begin |
5815 begin |
5816 StopSoundChan(Gear^.SoundChannel, 300); |
|
5296 DeleteGear(gear); |
5817 DeleteGear(gear); |
5297 exit |
5818 exit |
5298 end; |
5819 end; |
5299 HedgehogChAngle(HHGear); |
5820 HedgehogChAngle(HHGear); |
5300 gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); |
5821 gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); |
5329 speed := _0_5 * (_10 / Gear^.Tag); |
5850 speed := _0_5 * (_10 / Gear^.Tag); |
5330 |
5851 |
5331 flame:= AddGear(gx, gy, gtFlame, gstTmpFlag, |
5852 flame:= AddGear(gx, gy, gtFlame, gstTmpFlag, |
5332 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, |
5853 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, |
5333 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); |
5854 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); |
5334 flame^.CollisionMask:= lfNotCurrentMask; |
5855 flame^.CollisionMask:= lfNotCurHogCrate; |
5335 //flame^.FlightTime:= 500; use the default huge value to avoid sticky flame suddenly being damaging as opposed to other flames |
|
5336 |
5856 |
5337 if (Gear^.Health mod 30) = 0 then |
5857 if (Gear^.Health mod 30) = 0 then |
5338 begin |
5858 begin |
5339 flame:= AddGear(gx, gy, gtFlame, 0, |
5859 flame:= AddGear(gx, gy, gtFlame, 0, |
5340 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, |
5860 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, |
5341 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); |
5861 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); |
5342 flame^.CollisionMask:= lfNotCurrentMask; |
5862 flame^.CollisionMask:= lfNotCurHogCrate; |
5343 //flame^.FlightTime:= 500; |
|
5344 end |
5863 end |
5345 end; |
5864 end; |
5346 Gear^.Timer:= Gear^.Tag |
5865 Gear^.Timer:= Gear^.Tag |
5347 end; |
5866 end; |
5348 |
5867 |
5349 if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) then |
5868 if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) then |
5350 begin |
5869 begin |
5870 HHGear^.Message:= HHGear^.Message and (not (gmAttack or gmLeft or gmRight)); |
|
5351 HHGear^.State := HHGear^.State and (not gstNotKickable); |
5871 HHGear^.State := HHGear^.State and (not gstNotKickable); |
5872 StopSoundChan(Gear^.SoundChannel, 300); |
|
5352 DeleteGear(Gear); |
5873 DeleteGear(Gear); |
5353 AfterAttack |
5874 AfterAttack |
5354 end |
5875 end |
5355 else |
5876 else |
5356 begin |
5877 begin |
5357 i:= Gear^.Health div 5; |
5878 i:= Gear^.Health div 5; |
5358 if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
5879 if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
5359 begin |
5880 begin |
5360 Gear^.Damage:= i; |
5881 Gear^.Damage:= i; |
5361 FreeAndNilTexture(Gear^.Tex); |
5882 FreeAndNilTexture(Gear^.Tex); |
5362 Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(i) + |
5883 Gear^.Tex := RenderStringTex(FormatA(trmsg[sidFuel], ansistring(inttostr(i))), |
5363 '%'), cWhiteColor, fntSmall) |
5884 cWhiteColor, fntSmall) |
5364 end |
5885 end |
5365 end |
5886 end |
5366 end; |
5887 end; |
5367 |
5888 |
5368 procedure doStepFlamethrower(Gear: PGear); |
5889 procedure doStepFlamethrower(Gear: PGear); |
5370 HHGear: PGear; |
5891 HHGear: PGear; |
5371 begin |
5892 begin |
5372 HHGear := Gear^.Hedgehog^.Gear; |
5893 HHGear := Gear^.Hedgehog^.Gear; |
5373 HHGear^.Message := HHGear^.Message and (not (gmUp or gmDown or gmLeft or gmRight)); |
5894 HHGear^.Message := HHGear^.Message and (not (gmUp or gmDown or gmLeft or gmRight)); |
5374 HHGear^.State := HHGear^.State or gstNotKickable; |
5895 HHGear^.State := HHGear^.State or gstNotKickable; |
5896 (* NOTE: Flamethrower sound is supposed to start instantly (no fade in), |
|
5897 but this would cause the game volume to screw up because of a bug in SDL_mixer: |
|
5898 https://bugzilla.libsdl.org/show_bug.cgi?id=4205 |
|
5899 As workaround, a tiny fade-in delay was added. |
|
5900 FIXME: Remove the fade-in delay argument when the SDL bug has been fixed. *) |
|
5901 Gear^.SoundChannel := LoopSound(sndFlamethrower, 20); |
|
5375 Gear^.doStep := @doStepFlamethrowerWork |
5902 Gear^.doStep := @doStepFlamethrowerWork |
5376 end; |
5903 end; |
5377 |
5904 |
5378 //////////////////////////////////////////////////////////////////////////////// |
5905 //////////////////////////////////////////////////////////////////////////////// |
5379 procedure doStepLandGunWork(Gear: PGear); |
5906 procedure doStepLandGunWork(Gear: PGear); |
5384 begin |
5911 begin |
5385 AllInactive := false; |
5912 AllInactive := false; |
5386 HHGear := Gear^.Hedgehog^.Gear; |
5913 HHGear := Gear^.Hedgehog^.Gear; |
5387 if HHGear = nil then |
5914 if HHGear = nil then |
5388 begin |
5915 begin |
5916 StopSoundChan(gear^.SoundChannel); |
|
5389 DeleteGear(gear); |
5917 DeleteGear(gear); |
5390 exit |
5918 exit |
5391 end; |
5919 end; |
5392 HedgehogChAngle(HHGear); |
5920 HedgehogChAngle(HHGear); |
5393 gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); |
5921 gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle); |
5421 speed := (_3 / Gear^.Tag); |
5949 speed := (_3 / Gear^.Tag); |
5422 |
5950 |
5423 land:= AddGear(gx, gy, gtFlake, gstTmpFlag, |
5951 land:= AddGear(gx, gy, gtFlake, gstTmpFlag, |
5424 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, |
5952 SignAs(AngleSin(HHGear^.Angle) * speed, HHGear^.dX) + rx, |
5425 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); |
5953 AngleCos(HHGear^.Angle) * ( - speed) + ry, 0); |
5426 land^.CollisionMask:= lfNotCurrentMask; |
5954 land^.CollisionMask:= lfNotCurHogCrate; |
5427 |
5955 |
5428 Gear^.Timer:= Gear^.Tag |
5956 Gear^.Timer:= Gear^.Tag |
5429 end; |
5957 end; |
5430 |
5958 |
5431 if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) or ((HHGear^.Message and gmAttack) <> 0) then |
5959 if (Gear^.Health = 0) or ((HHGear^.State and gstHHDriven) = 0) or ((HHGear^.Message and gmAttack) <> 0) then |
5432 begin |
5960 begin |
5433 HHGear^.Message:= HHGear^.Message and (not gmAttack); |
5961 HHGear^.Message:= HHGear^.Message and (not (gmAttack or gmLeft or gmRight)); |
5434 HHGear^.State := HHGear^.State and (not gstNotKickable); |
5962 HHGear^.State := HHGear^.State and (not gstNotKickable); |
5963 StopSoundChan(gear^.SoundChannel); |
|
5435 DeleteGear(Gear); |
5964 DeleteGear(Gear); |
5436 AfterAttack |
5965 AfterAttack |
5437 end |
5966 end |
5438 else |
5967 else |
5439 begin |
5968 begin |
5440 i:= Gear^.Health div 10; |
5969 i:= Gear^.Health div 10; |
5441 if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
5970 if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
5442 begin |
5971 begin |
5443 Gear^.Damage:= i; |
5972 Gear^.Damage:= i; |
5444 FreeAndNilTexture(Gear^.Tex); |
5973 FreeAndNilTexture(Gear^.Tex); |
5445 Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(i) + |
5974 Gear^.Tex := RenderStringTex(FormatA(trmsg[sidFuel], ansistring(inttostr(i))), |
5446 '%'), cWhiteColor, fntSmall) |
5975 cWhiteColor, fntSmall) |
5447 end |
5976 end |
5448 end |
5977 end |
5449 end; |
5978 end; |
5450 |
5979 |
5451 procedure doStepLandGun(Gear: PGear); |
5980 procedure doStepLandGun(Gear: PGear); |
5453 HHGear: PGear; |
5982 HHGear: PGear; |
5454 begin |
5983 begin |
5455 HHGear := Gear^.Hedgehog^.Gear; |
5984 HHGear := Gear^.Hedgehog^.Gear; |
5456 HHGear^.Message := HHGear^.Message and (not (gmUp or gmDown or gmLeft or gmRight or gmAttack)); |
5985 HHGear^.Message := HHGear^.Message and (not (gmUp or gmDown or gmLeft or gmRight or gmAttack)); |
5457 HHGear^.State := HHGear^.State or gstNotKickable; |
5986 HHGear^.State := HHGear^.State or gstNotKickable; |
5987 Gear^.SoundChannel := LoopSound(sndLandGun); |
|
5458 Gear^.doStep := @doStepLandGunWork |
5988 Gear^.doStep := @doStepLandGunWork |
5459 end; |
5989 end; |
5460 |
5990 |
5461 //////////////////////////////////////////////////////////////////////////////// |
5991 //////////////////////////////////////////////////////////////////////////////// |
5462 procedure doStepPoisonCloud(Gear: PGear); |
5992 procedure doStepPoisonCloud(Gear: PGear); |
5505 tmp:= t^.ar[i]; |
6035 tmp:= t^.ar[i]; |
5506 if (tmp^.State and gstNoDamage) = 0 then |
6036 if (tmp^.State and gstNoDamage) = 0 then |
5507 if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then |
6037 if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then |
5508 begin |
6038 begin |
5509 dmg:= 0; |
6039 dmg:= 0; |
5510 //tmp^.State:= tmp^.State or gstFlatened; |
|
5511 if (tmp^.Kind <> gtHedgehog) or (tmp^.Hedgehog^.Effects[heInvulnerable] = 0) then |
6040 if (tmp^.Kind <> gtHedgehog) or (tmp^.Hedgehog^.Effects[heInvulnerable] = 0) then |
5512 begin |
6041 begin |
5513 // base damage on remaining health |
6042 // base damage on remaining health |
5514 dmg:= (tmp^.Health - tmp^.Damage); |
6043 dmg:= (tmp^.Health - tmp^.Damage); |
5515 if dmg > 0 then |
6044 if dmg > 0 then |
5516 begin |
6045 begin |
5517 // always rounding down |
6046 // always rounding down |
5518 dmg:= dmg div Gear^.Boom; |
6047 dmg:= dmg div Gear^.Boom; |
5519 |
6048 |
5520 if dmg > 0 then |
6049 if dmg > 0 then |
5521 ApplyDamage(tmp, CurrentHedgehog, dmg, dsUnknown); |
6050 ApplyDamage(tmp, CurrentHedgehog, dmg, dsHammer); |
5522 end; |
6051 end; |
5523 tmp^.dY:= _0_03 * Gear^.Boom |
6052 tmp^.dY:= _0_03 * Gear^.Boom |
5524 end; |
6053 end; |
5525 |
6054 |
5526 if (tmp^.Kind <> gtHedgehog) or (dmg > 0) or (tmp^.Health > tmp^.Damage) then |
6055 if (tmp^.Kind <> gtHedgehog) or (dmg > 0) or (tmp^.Health > tmp^.Damage) then |
5527 begin |
6056 begin |
5528 //DrawTunnel(tmp^.X, tmp^.Y - _1, _0, _0_5, cHHRadius * 6, cHHRadius * 3); |
|
5529 tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0); |
6057 tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0); |
5530 tmp2^.LinkedGear:= tmp; |
6058 tmp2^.LinkedGear:= tmp; |
5531 SetAllToActive |
6059 SetAllToActive |
5532 end; |
6060 end; |
5533 end; |
6061 end; |
5556 begin |
6084 begin |
5557 AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust); |
6085 AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust); |
5558 |
6086 |
5559 i := hwRound(Gear^.X) - HitGear^.Radius + 2; |
6087 i := hwRound(Gear^.X) - HitGear^.Radius + 2; |
5560 ei := hwRound(Gear^.X) + HitGear^.Radius - 2; |
6088 ei := hwRound(Gear^.X) + HitGear^.Radius - 2; |
5561 for j := 1 to 4 do DrawExplosion(i - GetRandom(5), hwRound(Gear^.Y) + 6*j, 3); |
6089 for j := 1 to 4 do doMakeExplosion(i - GetRandom(5), hwRound(Gear^.Y) + 6*j, 3, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx or EXPLForceDraw); |
5562 for j := 1 to 4 do DrawExplosion(ei + LongInt(GetRandom(5)), hwRound(Gear^.Y) + 6*j, 3); |
6090 for j := 1 to 4 do doMakeExplosion(ei + LongInt(GetRandom(5)), hwRound(Gear^.Y) + 6*j, 3, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx or EXPLForceDraw); |
5563 while i <= ei do |
6091 while i <= ei do |
5564 begin |
6092 begin |
5565 for j := 1 to 11 do DrawExplosion(i, hwRound(Gear^.Y) + 3*j, 3); |
6093 for j := 1 to 11 do doMakeExplosion(i, hwRound(Gear^.Y) + 3*j, 3, Gear^.Hedgehog, EXPLNoDamage or EXPLDoNotTouchAny or EXPLNoGfx or EXPLForceDraw); |
5566 inc(i, 1) |
6094 inc(i, 1) |
5567 end; |
6095 end; |
5568 |
6096 |
5569 if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9) |
6097 if CheckLandValue(hwRound(Gear^.X + Gear^.dX + SignAs(_6,Gear^.dX)), hwRound(Gear^.Y + _1_9) |
5570 , lfIndestructible) then |
6098 , lfIndestructible) then |
5571 begin |
6099 begin |
5572 //Gear^.X := Gear^.X + Gear^.dX; |
|
5573 Gear^.Y := Gear^.Y + _1_9 |
6100 Gear^.Y := Gear^.Y + _1_9 |
5574 end; |
6101 end; |
5575 end; |
6102 end; |
5576 if TestCollisionYwithGear(Gear, 1) <> 0 then |
6103 if TestCollisionYwithGear(Gear, 1) <> 0 then |
5577 begin |
6104 begin |
5579 SetLittle(HitGear^.dX); |
6106 SetLittle(HitGear^.dX); |
5580 HitGear^.dY := _0; |
6107 HitGear^.dY := _0; |
5581 end |
6108 end |
5582 else |
6109 else |
5583 begin |
6110 begin |
5584 //Gear^.dY := Gear^.dY + cGravity; |
|
5585 //Gear^.Y := Gear^.Y + Gear^.dY; |
|
5586 if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then |
6111 if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then |
5587 Gear^.Timer := 1 |
6112 Gear^.Timer := 1 |
5588 end; |
6113 end; |
5589 |
6114 |
5590 //Gear^.X := Gear^.X + HitGear^.dX; |
|
5591 HitGear^.X := Gear^.X; |
6115 HitGear^.X := Gear^.X; |
5592 HitGear^.Y := Gear^.Y; |
6116 HitGear^.Y := Gear^.Y; |
5593 SetLittle(HitGear^.dY); |
6117 SetLittle(HitGear^.dY); |
5594 HitGear^.Active:= true; |
6118 HitGear^.Active:= true; |
5595 end; |
6119 end; |
5627 resgear: PGear; |
6151 resgear: PGear; |
5628 hh: PHedgehog; |
6152 hh: PHedgehog; |
5629 i: LongInt; |
6153 i: LongInt; |
5630 s: ansistring; |
6154 s: ansistring; |
5631 begin |
6155 begin |
5632 if (TurnTimeLeft > 0) then |
|
5633 dec(TurnTimeLeft); |
|
5634 |
|
5635 AllInactive := false; |
6156 AllInactive := false; |
5636 hh := Gear^.Hedgehog; |
6157 hh := Gear^.Hedgehog; |
5637 |
|
5638 // no, you can't do that here |
|
5639 {DrawCentered(hwRound(hh^.Gear^.X) + WorldDx, hwRound(hh^.Gear^.Y) + WorldDy - |
|
5640 cHHRadius - 14 - hh^.HealthTagTex^.h, hh^.HealthTagTex); |
|
5641 } |
|
5642 (*DrawCircle(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, 1.5, 0, 0, $FF, |
|
5643 $FF);*) |
|
5644 |
6158 |
5645 if ((Gear^.Message and gmUp) <> 0) then |
6159 if ((Gear^.Message and gmUp) <> 0) then |
5646 begin |
6160 begin |
5647 if (GameTicks and $F) <> 0 then |
6161 if (GameTicks and $F) <> 0 then |
5648 exit; |
6162 exit; |
5675 hh^.Gear^.Damage:= 1; |
6189 hh^.Gear^.Damage:= 1; |
5676 RenderHealth(hh^); |
6190 RenderHealth(hh^); |
5677 RecountTeamHealth(hh^.Team); |
6191 RecountTeamHealth(hh^.Team); |
5678 inc(graves.ar^[Gear^.Tag]^.Health); |
6192 inc(graves.ar^[Gear^.Tag]^.Health); |
5679 inc(Gear^.Tag) |
6193 inc(Gear^.Tag) |
5680 {-for i:= 0 to High(graves) do begin |
|
5681 if hh^.Gear^.Health > 0 then begin |
|
5682 dec(hh^.Gear^.Health); |
|
5683 inc(graves[i]^.Health); |
|
5684 end; |
|
5685 end; -} |
|
5686 end |
6194 end |
5687 else |
6195 else |
5688 begin |
6196 begin |
5689 // now really resurrect the hogs with the hp saved in the graves |
6197 // now really resurrect the hogs with the hp saved in the graves |
5690 for i:= 0 to graves.size - 1 do |
6198 for i:= 0 to graves.size - 1 do |
5697 graves.ar^[i]^.Message:= graves.ar^[i]^.Message or gmDestroy; |
6205 graves.ar^[i]^.Message:= graves.ar^[i]^.Message or gmDestroy; |
5698 graves.ar^[i]^.Active:= true; |
6206 graves.ar^[i]^.Active:= true; |
5699 RenderHealth(resgear^.Hedgehog^); |
6207 RenderHealth(resgear^.Hedgehog^); |
5700 RecountTeamHealth(resgear^.Hedgehog^.Team); |
6208 RecountTeamHealth(resgear^.Hedgehog^.Team); |
5701 resgear^.Hedgehog^.Effects[heResurrected]:= 1; |
6209 resgear^.Hedgehog^.Effects[heResurrected]:= 1; |
6210 if resgear^.Hedgehog^.King then |
|
6211 resgear^.Hedgehog^.Team^.hasKing:= true; |
|
6212 { Reviving a hog implies its clan is now alive, too. } |
|
6213 resgear^.Hedgehog^.Team^.Clan^.DeathLogged:= false; |
|
6214 if (not resgear^.Hedgehog^.Team^.Passive) then |
|
6215 resgear^.Hedgehog^.Team^.Clan^.Passive:= false; |
|
5702 s:= ansistring(resgear^.Hedgehog^.Name); |
6216 s:= ansistring(resgear^.Hedgehog^.Name); |
5703 AddCaption(FormatA(GetEventString(eidResurrected), s), cWhiteColor, capgrpMessage); |
6217 AddCaption(FormatA(GetEventString(eidResurrected), s), capcolDefault, capgrpMessage); |
5704 // only make hat-less hedgehogs look like zombies, preserve existing hats |
6218 // only make hat-less hedgehogs look like zombies, preserve existing hats |
5705 |
6219 |
5706 if resgear^.Hedgehog^.Hat = 'NoHat' then |
6220 if resgear^.Hedgehog^.Hat = 'NoHat' then |
5707 LoadHedgehogHat(resgear^.Hedgehog^, 'Reserved/Zombie'); |
6221 LoadHedgehogHat(resgear^.Hedgehog^, 'Reserved/Zombie'); |
5708 end; |
6222 end; |
5712 doStepHedgehogMoving(hh^.Gear); |
6226 doStepHedgehogMoving(hh^.Gear); |
5713 StopSoundChan(Gear^.SoundChannel); |
6227 StopSoundChan(Gear^.SoundChannel); |
5714 Gear^.Timer := 250; |
6228 Gear^.Timer := 250; |
5715 Gear^.doStep := @doStepIdle; |
6229 Gear^.doStep := @doStepIdle; |
5716 end |
6230 end |
5717 //if hh^.Gear^.Health = 0 then doStepHedgehogFree(hh^.Gear); |
|
5718 end; |
6231 end; |
5719 |
6232 |
5720 procedure doStepResurrector(Gear: PGear); |
6233 procedure doStepResurrector(Gear: PGear); |
5721 var |
6234 var |
5722 graves: PGearArrayS; |
6235 graves: PGearArrayS; |
5790 end; |
6303 end; |
5791 if (GameTicks and $3F) = 0 then |
6304 if (GameTicks and $3F) = 0 then |
5792 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
6305 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace); |
5793 dec(Gear^.Timer) |
6306 dec(Gear^.Timer) |
5794 end; |
6307 end; |
5795 |
|
5796 (* |
|
5797 //////////////////////////////////////////////////////////////////////////////// |
|
5798 procedure doStepStructure(Gear: PGear); |
|
5799 var |
|
5800 x, y: LongInt; |
|
5801 HH: PHedgehog; |
|
5802 t: PGear; |
|
5803 begin |
|
5804 HH:= Gear^.Hedgehog; |
|
5805 |
|
5806 if (Gear^.State and gstMoving) <> 0 then |
|
5807 begin |
|
5808 AddCI(Gear); |
|
5809 Gear^.dX:= _0; |
|
5810 Gear^.dY:= _0; |
|
5811 Gear^.State:= Gear^.State and (not gstMoving); |
|
5812 end; |
|
5813 |
|
5814 dec(Gear^.Health, Gear^.Damage); |
|
5815 Gear^.Damage:= 0; |
|
5816 |
|
5817 if Gear^.Pos = 1 then |
|
5818 begin |
|
5819 AddCI(Gear); |
|
5820 AfterAttack; |
|
5821 if Gear = CurAmmoGear then |
|
5822 CurAmmoGear:= nil; |
|
5823 if HH^.Gear <> nil then |
|
5824 HideHog(HH); |
|
5825 Gear^.Pos:= 2 |
|
5826 end; |
|
5827 |
|
5828 if Gear^.Pos = 2 then |
|
5829 begin |
|
5830 if ((GameTicks mod 100) = 0) and (Gear^.Timer < 1000) then |
|
5831 begin |
|
5832 if (Gear^.Timer mod 10) = 0 then |
|
5833 begin |
|
5834 DeleteCI(Gear); |
|
5835 Gear^.Y:= Gear^.Y - _0_5; |
|
5836 AddCI(Gear); |
|
5837 end; |
|
5838 inc(Gear^.Timer); |
|
5839 end; |
|
5840 if Gear^.Tag <= TotalRounds then |
|
5841 Gear^.Pos:= 3; |
|
5842 end; |
|
5843 |
|
5844 if Gear^.Pos = 3 then |
|
5845 if Gear^.Timer < 1000 then |
|
5846 begin |
|
5847 if (Gear^.Timer mod 10) = 0 then |
|
5848 begin |
|
5849 DeleteCI(Gear); |
|
5850 Gear^.Y:= Gear^.Y - _0_5; |
|
5851 AddCI(Gear); |
|
5852 end; |
|
5853 inc(Gear^.Timer); |
|
5854 end |
|
5855 else |
|
5856 begin |
|
5857 if HH^.GearHidden <> nil then |
|
5858 RestoreHog(HH); |
|
5859 Gear^.Pos:= 4; |
|
5860 end; |
|
5861 |
|
5862 if Gear^.Pos = 4 then |
|
5863 if ((GameTicks mod 1000) = 0) and ((GameFlags and gfInvulnerable) = 0) then |
|
5864 begin |
|
5865 t:= GearsList; |
|
5866 while t <> nil do |
|
5867 begin |
|
5868 if (t^.Kind = gtHedgehog) and (t^.Hedgehog^.Team^.Clan = HH^.Team^.Clan) then |
|
5869 t^.Hedgehog^.Effects[heInvulnerable]:= 1; |
|
5870 t:= t^.NextGear; |
|
5871 end; |
|
5872 end; |
|
5873 |
|
5874 if Gear^.Health <= 0 then |
|
5875 begin |
|
5876 if HH^.GearHidden <> nil then |
|
5877 RestoreHog(HH); |
|
5878 |
|
5879 x := hwRound(Gear^.X); |
|
5880 y := hwRound(Gear^.Y); |
|
5881 |
|
5882 DeleteCI(Gear); |
|
5883 DeleteGear(Gear); |
|
5884 |
|
5885 doMakeExplosion(x, y, 50, CurrentHedgehog, EXPLAutoSound); |
|
5886 end; |
|
5887 end; |
|
5888 *) |
|
5889 |
6308 |
5890 //////////////////////////////////////////////////////////////////////////////// |
6309 //////////////////////////////////////////////////////////////////////////////// |
5891 (* |
6310 (* |
5892 TARDIS needs |
6311 TARDIS needs |
5893 Warp in. Pos = 1 |
6312 Warp in. Pos = 1 |
5905 var HH: PHedgehog; |
6324 var HH: PHedgehog; |
5906 i,j,cnt: LongWord; |
6325 i,j,cnt: LongWord; |
5907 s: ansistring; |
6326 s: ansistring; |
5908 begin |
6327 begin |
5909 HH:= Gear^.Hedgehog; |
6328 HH:= Gear^.Hedgehog; |
6329 if Gear^.Tag = 0 then |
|
6330 begin |
|
6331 if HH^.Gear <> nil then |
|
6332 begin |
|
6333 if (HH^.Gear^.Damage <> 0) or (HH^.Gear^.Health = 0) or |
|
6334 ((HH^.Gear^.State and (gstMoving or gstHHDeath or gstHHGone or gstDrowning)) <> 0) then |
|
6335 begin |
|
6336 Gear^.Tag:= 1; |
|
6337 HH^.Gear^.State:= HH^.Gear^.State and (not gstAttacking); |
|
6338 HH^.Gear^.Message:= HH^.Gear^.Message and (not gmAttack); |
|
6339 AfterAttack; |
|
6340 end; |
|
6341 end |
|
6342 else if HH^.GearHidden = nil then |
|
6343 Gear^.Tag:= 1; |
|
6344 if (Gear^.Tag = 1) and (Gear = CurAmmoGear) then |
|
6345 CurAmmoGear:= nil; |
|
6346 end; |
|
6347 |
|
5910 if Gear^.Pos = 2 then |
6348 if Gear^.Pos = 2 then |
5911 begin |
6349 begin |
5912 StopSoundChan(Gear^.SoundChannel); |
6350 StopSoundChan(Gear^.SoundChannel); |
5913 Gear^.SoundChannel:= -1; |
6351 Gear^.SoundChannel:= -1; |
5914 if (Gear^.Timer = 0) then |
6352 if (Gear^.Timer = 0) then |
5915 begin |
6353 begin |
5916 if (HH^.Gear <> nil) and (HH^.Gear^.State and gstInvisible = 0) then |
6354 if (HH^.Gear <> nil) and (HH^.Gear^.State and gstInvisible = 0) then |
5917 begin |
6355 begin |
5918 AfterAttack; |
6356 if Gear^.Tag = 0 then |
5919 if Gear = CurAmmoGear then CurAmmoGear := nil; |
6357 AfterAttack; |
5920 if (HH^.Gear^.Damage = 0) and (HH^.Gear^.Health > 0) and |
6358 if Gear = CurAmmoGear then |
5921 ((Gear^.State and (gstMoving or gstHHDeath or gstHHGone)) = 0) then |
6359 CurAmmoGear:= nil; |
5922 HideHog(HH) |
6360 if Gear^.Tag = 0 then |
6361 HideHog(HH); |
|
5923 end |
6362 end |
5924 //else if (HH^.Gear <> nil) and (HH^.Gear^.State and gstInvisible <> 0) then |
6363 else if (HH^.GearHidden <> nil) then |
5925 else if (HH^.GearHidden <> nil) then// and (HH^.Gear^.State and gstInvisible <> 0) then |
|
5926 begin |
6364 begin |
5927 RestoreHog(HH); |
6365 RestoreHog(HH); |
5928 s:= ansistring(HH^.Name); |
6366 s:= ansistring(HH^.Name); |
5929 AddCaption(FormatA(GetEventString(eidTimeTravelEnd), s), cWhiteColor, capgrpMessage) |
6367 AddCaption(FormatA(GetEventString(eidTimeTravelEnd), s), capcolDefault, capgrpMessage) |
5930 end |
6368 end |
5931 end; |
6369 end; |
5932 |
6370 |
5933 inc(Gear^.Timer); |
6371 inc(Gear^.Timer); |
5934 if (Gear^.Timer > 2000) and ((GameTicks mod 2000) = 1000) then |
6372 if (Gear^.Timer > 2000) and ((GameTicks mod 2000) = 1000) then |
5940 |
6378 |
5941 if (Gear^.Pos = 1) and (GameTicks and $1F = 0) and (Gear^.Power < 255) then |
6379 if (Gear^.Pos = 1) and (GameTicks and $1F = 0) and (Gear^.Power < 255) then |
5942 begin |
6380 begin |
5943 inc(Gear^.Power); |
6381 inc(Gear^.Power); |
5944 if (Gear^.Power = 172) and (HH^.Gear <> nil) and |
6382 if (Gear^.Power = 172) and (HH^.Gear <> nil) and |
5945 (HH^.Gear^.Damage = 0) and (HH^.Gear^.Health > 0) and |
6383 (Gear^.Tag = 0) then |
5946 ((HH^.Gear^.State and (gstMoving or gstHHDeath or gstHHGone)) = 0) then |
|
5947 with HH^.Gear^ do |
6384 with HH^.Gear^ do |
5948 begin |
6385 begin |
5949 State:= State or gstAnimation; |
6386 State:= State or gstAnimation; |
5950 Tag:= 2; |
6387 Tag:= 2; |
5951 Timer:= 0; |
6388 Timer:= 0; |
6026 end; |
6463 end; |
6027 |
6464 |
6028 //////////////////////////////////////////////////////////////////////////////// |
6465 //////////////////////////////////////////////////////////////////////////////// |
6029 |
6466 |
6030 (* |
6467 (* |
6031 WIP. The ice gun will have the following effects. It has been proposed by sheepluva that it take the appearance of a large freezer |
6468 The ice gun has the following effects: |
6032 spewing ice cubes. The cubes will be visual gears only. The scatter from them and the impact snow dust should help hide imprecisions in things like the GearsNear effect. |
6469 A "ray" like a deagle is projected out from the gun. |
6033 For now we assume a "ray" like a deagle projected out from the gun. |
|
6034 All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks. This is a simplifying assumption for "gun was applying freezing effect to the same target". |
6470 All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks. This is a simplifying assumption for "gun was applying freezing effect to the same target". |
6035 * When fired at water a layer of ice textured land is added above the water. |
6471 * When fired at water a layer of ice textured land is added above the water. |
6036 * When fired at non-ice land (land and lfLandMask and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed. |
6472 * When fired at non-ice land (land and lfLandMask and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed. |
6037 * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen. |
6473 * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen. |
6038 As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head. |
6474 As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head. |
6039 If the effect is interrupted before reaching the top, the freezing state is cleared. |
6475 If the effect is interrupted before reaching the top, the freezing state is cleared. |
6040 A frozen hog will animate differently. |
6476 A frozen hog will animate differently. |
6041 To be decided, but possibly in a similar fashion to a grave when it comes to explosions. |
6477 Frozen hogs take less damage and are harder to push. |
6042 The hog might (possibly) not be damaged by explosions. |
|
6043 This might make freezing potentially useful for friendlies in a bad position. |
6478 This might make freezing potentially useful for friendlies in a bad position. |
6044 It might be better to allow damage though. |
|
6045 A frozen hog stays frozen for a certain number of turns. |
6479 A frozen hog stays frozen for a certain number of turns. |
6046 Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again. |
6480 Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again. |
6047 *) |
6481 *) |
6048 |
6482 |
6049 |
6483 |
6054 t:= Gear^.Health div 10; |
6488 t:= Gear^.Health div 10; |
6055 if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
6489 if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then |
6056 begin |
6490 begin |
6057 Gear^.Damage:= t; |
6491 Gear^.Damage:= t; |
6058 FreeAndNilTexture(Gear^.Tex); |
6492 FreeAndNilTexture(Gear^.Tex); |
6059 Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ansistring(': ' + inttostr(t) + |
6493 Gear^.Tex := RenderStringTex(FormatA(trmsg[sidFuel], ansistring(inttostr(t))), |
6060 '%'), cWhiteColor, fntSmall) |
6494 cWhiteColor, fntSmall) |
6061 end; |
6495 end; |
6062 if Gear^.Message and (gmUp or gmDown) <> 0 then |
6496 if Gear^.Message and (gmUp or gmDown) <> 0 then |
6063 begin |
6497 begin |
6064 StopSoundChan(Gear^.SoundChannel); |
6498 if (Gear^.Tag <> 2) then |
6065 Gear^.SoundChannel:= -1; |
6499 begin |
6500 StopSoundChan(Gear^.SoundChannel); |
|
6501 Gear^.SoundChannel:= LoopSound(sndIceBeamIdle); |
|
6502 Gear^.Tag:= 2; |
|
6503 end; |
|
6066 if GameTicks mod 40 = 0 then dec(Gear^.Health) |
6504 if GameTicks mod 40 = 0 then dec(Gear^.Health) |
6067 end |
6505 end |
6068 else |
6506 else |
6069 begin |
6507 begin |
6070 if Gear^.SoundChannel = -1 then |
6508 if (Gear^.Tag <> 1) then |
6071 Gear^.SoundChannel := LoopSound(sndIceBeam); |
6509 begin |
6510 StopSoundChan(Gear^.SoundChannel); |
|
6511 Gear^.SoundChannel:= LoopSound(sndIceBeam); |
|
6512 Gear^.Tag:= 1; |
|
6513 end; |
|
6072 if GameTicks mod 10 = 0 then dec(Gear^.Health) |
6514 if GameTicks mod 10 = 0 then dec(Gear^.Health) |
6073 end |
6515 end |
6074 end; |
6516 end; |
6075 |
6517 |
6076 |
6518 |
6077 procedure updateTarget(Gear:PGear; newX, newY:HWFloat); |
6519 procedure updateTarget(Gear:PGear; newX, newY:HWFloat); |
6078 // var |
|
6079 // iter:PGear; |
|
6080 begin |
6520 begin |
6081 with Gear^ do |
6521 with Gear^ do |
6082 begin |
6522 begin |
6083 dX:= newX; |
6523 dX:= newX; |
6084 dY:= newY; |
6524 dY:= newY; |
6091 end; |
6531 end; |
6092 |
6532 |
6093 procedure doStepIceGun(Gear: PGear); |
6533 procedure doStepIceGun(Gear: PGear); |
6094 const iceWaitCollision = 0; |
6534 const iceWaitCollision = 0; |
6095 const iceCollideWithGround = 1; |
6535 const iceCollideWithGround = 1; |
6096 //const iceWaitNextTarget:Longint = 2; |
|
6097 //const iceCollideWithHog:Longint = 4; |
|
6098 const iceCollideWithWater = 5; |
6536 const iceCollideWithWater = 5; |
6099 //const waterFreezingTime:Longint = 500; |
|
6100 const groundFreezingTime = 1000; |
6537 const groundFreezingTime = 1000; |
6101 const iceRadius = 32; |
6538 const iceRadius = 32; |
6102 const iceHeight = 40; |
6539 const iceHeight = 40; |
6103 var |
6540 var |
6104 HHGear, iter: PGear; |
6541 HHGear, iter: PGear; |
6115 DeleteGear(Gear); |
6552 DeleteGear(Gear); |
6116 AfterAttack; |
6553 AfterAttack; |
6117 exit |
6554 exit |
6118 end; |
6555 end; |
6119 updateFuel(Gear); |
6556 updateFuel(Gear); |
6557 if (WorldEdge <> weBounce) then |
|
6558 if WorldWrap(Gear) and (WorldEdge = weWrap) and (Gear^.Target.X = NoPointX) then |
|
6559 // Use FlightTime to count number of times the gear has world-wrapped |
|
6560 inc(Gear^.FlightTime); |
|
6120 |
6561 |
6121 with Gear^ do |
6562 with Gear^ do |
6122 begin |
6563 begin |
6123 HedgehogChAngle(HHGear); |
6564 HedgehogChAngle(HHGear); |
6124 ndX:= SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _4; |
6565 ndX:= SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _4; |
6125 ndY:= -AngleCos(HHGear^.Angle) * _4; |
6566 ndY:= -AngleCos(HHGear^.Angle) * _4; |
6126 if (ndX <> dX) or (ndY <> dY) or |
6567 if (ndX <> dX) or (ndY <> dY) or (Gear^.Message and (gmUp or gmDown) <> 0) or |
6127 ((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and |
6568 (((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and |
6128 (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0)) and |
6569 (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0)) and |
6129 (not CheckCoordInWater(Target.X, Target.Y))) then |
6570 (not CheckCoordInWater(Target.X, Target.Y))) and (CheckGearNear(gtAirMine, int2hwFloat(Target.X),int2hwFloat(Target.Y), Gear^.Radius*3, Gear^.Radius*3) = nil) and |
6571 (not ((WorldEdge = weBounce) and ((Target.X > rightX) or (Target.X < leftX))))) then |
|
6130 begin |
6572 begin |
6131 updateTarget(Gear, ndX, ndY); |
6573 updateTarget(Gear, ndX, ndY); |
6132 Timer := iceWaitCollision; |
6574 Timer := iceWaitCollision; |
6575 FlightTime := 0; |
|
6133 end |
6576 end |
6134 else |
6577 // Extend ice beam, unless it is far outside he map boundaries |
6578 else if (not ((hwRound(X + dX) > max(LAND_WIDTH,4096)*2) or |
|
6579 (hwRound(X + dX) < -max(LAND_WIDTH,4096)*2) or |
|
6580 (hwRound(Y + dY) < -max(LAND_HEIGHT,4096)*2) or |
|
6581 (hwRound(Y + dY) > max(LAND_HEIGHT,4096)+512))) then |
|
6135 begin |
6582 begin |
6136 X:= X + dX; |
6583 X:= X + dX; |
6137 Y:= Y + dY; |
6584 Y:= Y + dY; |
6138 gX:= hwRound(X); |
6585 gX:= hwRound(X); |
6139 gY:= hwRound(Y); |
6586 gY:= hwRound(Y); |
6140 if Target.X = NoPointX then t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y)); |
6587 if Target.X = NoPointX then t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y)); |
6141 |
6588 |
6142 if Target.X <> NoPointX then |
6589 if Target.X <> NoPointX then |
6143 begin |
6590 begin |
6144 CheckCollision(Gear); |
6591 CheckCollision(Gear); |
6145 if (State and gstCollision) <> 0 then |
6592 if ((State and gstCollision) <> 0) or (CheckGearNear(gtAirMine, int2hwFloat(Target.X),int2hwFloat(Target.Y), Gear^.Radius*4, Gear^.Radius*4) <> nil) then |
6146 begin |
6593 begin |
6147 if Timer = iceWaitCollision then |
6594 if Timer = iceWaitCollision then |
6148 begin |
6595 begin |
6149 Timer := iceCollideWithGround; |
6596 Timer := iceCollideWithGround; |
6150 Power := GameTicks; |
6597 Power := GameTicks; |
6154 ((Target.X and LAND_WIDTH_MASK = 0) and |
6601 ((Target.X and LAND_WIDTH_MASK = 0) and |
6155 (Target.Y and LAND_HEIGHT_MASK = 0) and |
6602 (Target.Y and LAND_HEIGHT_MASK = 0) and |
6156 (Land[Target.Y, Target.X] = lfIce) and |
6603 (Land[Target.Y, Target.X] = lfIce) and |
6157 ((Target.Y+iceHeight+5 > cWaterLine) or |
6604 ((Target.Y+iceHeight+5 > cWaterLine) or |
6158 ((WorldEdge = weSea) and |
6605 ((WorldEdge = weSea) and |
6159 ((Target.X+iceHeight+5 > LongInt(rightX)) or |
6606 ((Target.X+iceHeight+5 > rightX) or |
6160 (Target.X-iceHeight-5 < LongInt(leftX))))) |
6607 (Target.X-iceHeight-5 < leftX)))) |
6161 ) then |
6608 ) then |
6162 begin |
6609 begin |
6163 if Timer = iceWaitCollision then |
6610 if Timer = iceWaitCollision then |
6164 begin |
6611 begin |
6165 Timer := iceCollideWithWater; |
6612 Timer := iceCollideWithWater; |
6185 // Freeze nearby mines/explosives/cases too |
6632 // Freeze nearby mines/explosives/cases too |
6186 iter := GearsList; |
6633 iter := GearsList; |
6187 while iter <> nil do |
6634 while iter <> nil do |
6188 begin |
6635 begin |
6189 if (iter^.State and gstFrozen = 0) and |
6636 if (iter^.State and gstFrozen = 0) and |
6190 ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine) or (iter^.Kind = gtSMine)) and |
6637 ((iter^.Kind = gtExplosives) or (iter^.Kind = gtAirMine) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine) or (iter^.Kind = gtSMine)) and |
6191 (abs(LongInt(iter^.X.Round) - target.x) + abs(LongInt(iter^.Y.Round) - target.y) + 2 < 2 * iceRadius) |
6638 (abs(hwRound(iter^.X) - target.x) + abs(hwRound(iter^.Y) - target.y) + 2 < 2 * iceRadius) |
6192 and (Distance(iter^.X - int2hwFloat(target.x), iter^.Y - int2hwFloat(target.y)) < int2hwFloat(iceRadius * 2)) then |
6639 and (Distance(iter^.X - int2hwFloat(target.x), iter^.Y - int2hwFloat(target.y)) < int2hwFloat(iceRadius * 2)) then |
6193 begin |
6640 begin |
6194 for t:= 0 to 5 do |
6641 for t:= 0 to 5 do |
6195 begin |
6642 begin |
6196 vg:= AddVisualGear(hwRound(iter^.X)+random(4)-8, hwRound(iter^.Y)+random(8), vgtDust, 1); |
6643 vg:= AddVisualGear(hwRound(iter^.X)+random(4)-8, hwRound(iter^.Y)+random(8), vgtDust, 1); |
6229 begin |
6676 begin |
6230 DeleteCI(iter); |
6677 DeleteCI(iter); |
6231 iter^.State:= iter^.State or gstFrozen; |
6678 iter^.State:= iter^.State or gstFrozen; |
6232 AddCI(iter) |
6679 AddCI(iter) |
6233 end |
6680 end |
6681 else if iter^.Kind = gtAirMine then |
|
6682 begin |
|
6683 iter^.Damage:= 0; |
|
6684 iter^.State:= iter^.State or gstFrozen; |
|
6685 if (hwRound(iter^.X) < RightX-16) and (hwRound(iter^.X) > LeftX+16) and |
|
6686 (hwRound(iter^.Y) > topY+16) and (hwRound(iter^.Y) < LAND_HEIGHT-16) then |
|
6687 begin |
|
6688 AddCI(iter); |
|
6689 iter^.X:= int2hwFloat(min(RightX-16,max(hwRound(iter^.X), LeftX+16))); |
|
6690 iter^.Y:= int2hwFloat(min(LAND_HEIGHT-16,max(hwRound(iter^.Y),TopY+16))); |
|
6691 ForcePlaceOnLand(hwRound(iter^.X)-16, hwRound(iter^.Y)-16, sprFrozenAirMine, 0, lfIce, $FFFFFFFF, false, false, false); |
|
6692 iter^.State:= iter^.State or gstInvisible |
|
6693 end |
|
6694 else |
|
6695 begin |
|
6696 updateTarget(Gear, ndX, ndY); |
|
6697 FlightTime := 0; |
|
6698 Timer := iceWaitCollision; |
|
6699 Power := GameTicks; |
|
6700 iter^.State:= iter^.State and (not gstNoGravity) |
|
6701 end |
|
6702 end |
|
6234 else // gtExplosives |
6703 else // gtExplosives |
6235 begin |
6704 begin |
6236 iter^.State:= iter^.State or gstFrozen; |
6705 iter^.State:= iter^.State or gstFrozen; |
6237 iter^.Health:= iter^.Health + cBarrelHealth |
6706 iter^.Health:= iter^.Health + cBarrelHealth |
6238 end |
6707 end |
6239 end; |
6708 end; |
6240 iter:= iter^.NextGear |
6709 iter:= iter^.NextGear |
6241 end; |
6710 end; |
6242 |
6711 |
6243 // FillRoundInLandWithIce(Target.X, Target.Y, iceRadius); |
|
6244 SetAllHHToActive; |
6712 SetAllHHToActive; |
6245 Timer := iceWaitCollision; |
6713 Timer := iceWaitCollision; |
6714 Power:= GameTicks |
|
6246 end; |
6715 end; |
6247 |
6716 |
6248 if (Timer = iceCollideWithWater) and ((GameTicks - Power) > groundFreezingTime div 2) then |
6717 if (Timer = iceCollideWithWater) and ((GameTicks - Power) > groundFreezingTime div 2) then |
6249 begin |
6718 begin |
6250 PlaySound(sndHogFreeze); |
6719 PlaySound(sndHogFreeze); |
6251 if CheckCoordInWater(Target.X, Target.Y) then |
6720 if CheckCoordInWater(Target.X, Target.Y) then |
6252 DrawIceBreak(Target.X, Target.Y, iceRadius, iceHeight) |
6721 DrawIceBreak(Target.X, Target.Y, iceRadius, iceHeight) |
6253 else if Target.Y+iceHeight+5 > cWaterLine then |
6722 else if Target.Y+iceHeight+5 > cWaterLine then |
6254 DrawIceBreak(Target.X, Target.Y+iceHeight+5, iceRadius, iceHeight) |
6723 DrawIceBreak(Target.X, Target.Y+iceHeight+5, iceRadius, iceHeight) |
6255 else if Target.X+iceHeight+5 > LongInt(rightX) then |
6724 else if Target.X+iceHeight+5 > rightX then |
6256 DrawIceBreak(Target.X+iceHeight+5, Target.Y, iceRadius, iceHeight) |
6725 DrawIceBreak(Target.X+iceHeight+5, Target.Y, iceRadius, iceHeight) |
6257 else |
6726 else |
6258 DrawIceBreak(Target.X-iceHeight-5, Target.Y, iceRadius, iceHeight); |
6727 DrawIceBreak(Target.X-iceHeight-5, Target.Y, iceRadius, iceHeight); |
6259 SetAllHHToActive; |
6728 SetAllHHToActive; |
6260 Timer := iceWaitCollision; |
6729 Timer := iceWaitCollision; |
6261 end; |
6730 end; |
6262 (* |
|
6263 Any ideas for something that would look good here? |
|
6264 if (Target.X <> NoPointX) and ((Timer = iceCollideWithGround) or (Timer = iceCollideWithWater)) and (GameTicks mod max((groundFreezingTime-((GameTicks - Power)*2)),2) = 0) then //and CheckLandValue(Target.X, Target.Y, lfIce) then |
|
6265 begin |
|
6266 vg:= AddVisualGear(Target.X+random(20)-10, Target.Y+random(40)-10, vgtDust, 1); |
|
6267 if vg <> nil then |
|
6268 begin |
|
6269 i:= random(100) + 155; |
|
6270 vg^.Tint:= IceColor or $FF; |
|
6271 vg^.Angle:= random(360); |
|
6272 vg^.dx:= 0.001 * random(80); |
|
6273 vg^.dy:= 0.001 * random(80) |
|
6274 end |
|
6275 end; |
|
6276 *) |
|
6277 |
|
6278 // freeze nearby hogs |
6731 // freeze nearby hogs |
6279 hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2); |
6732 hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2); |
6280 if hogs.size > 0 then |
6733 if hogs.size > 0 then |
6281 for i:= 0 to hogs.size - 1 do |
6734 for i:= 0 to hogs.size - 1 do |
6282 if hogs.ar^[i] <> HHGear then |
6735 if hogs.ar^[i] <> HHGear then |
6299 begin |
6752 begin |
6300 Target.X:= gX; |
6753 Target.X:= gX; |
6301 Target.Y:= gY; |
6754 Target.Y:= gY; |
6302 X:= HHGear^.X; |
6755 X:= HHGear^.X; |
6303 Y:= HHGear^.Y |
6756 Y:= HHGear^.Y |
6304 end; |
6757 end |
6305 if (gX > max(LAND_WIDTH,4096)*2) or |
6758 else if (WorldEdge = weBounce) and ((gX > rightX) or (gX < leftX)) then |
6306 (gX < -max(LAND_WIDTH,4096)) or |
6759 begin |
6307 (gY < -max(LAND_HEIGHT,4096)) or |
|
6308 (gY > max(LAND_HEIGHT,4096)+512) then |
|
6309 begin |
|
6310 //X:= HHGear^.X; |
|
6311 //Y:= HHGear^.Y |
|
6312 Target.X:= gX; |
6760 Target.X:= gX; |
6313 Target.Y:= gY; |
6761 Target.Y:= gY; |
6762 X:= HHGear^.X; |
|
6763 Y:= HHGear^.Y |
|
6314 end |
6764 end |
6765 else |
|
6766 begin |
|
6767 iter:= CheckGearNear(Gear, gtAirMine, Gear^.Radius*2, Gear^.Radius*2); |
|
6768 if (iter <> nil) and (iter^.State <> gstFrozen) then |
|
6769 begin |
|
6770 Target.X:= gX; |
|
6771 Target.Y:= gY; |
|
6772 X:= HHGear^.X; |
|
6773 Y:= HHGear^.Y |
|
6774 end |
|
6775 end; |
|
6315 end |
6776 end |
6316 end; |
6777 end; |
6317 end; |
6778 end; |
6318 |
6779 |
6319 procedure doStepAddAmmo(Gear: PGear); |
6780 procedure doStepAddAmmo(Gear: PGear); |
6352 exit |
6813 exit |
6353 end; |
6814 end; |
6354 if (Gear^.State and gstTmpFlag <> 0) or (GameTicks and $7 = 0) then |
6815 if (Gear^.State and gstTmpFlag <> 0) or (GameTicks and $7 = 0) then |
6355 begin |
6816 begin |
6356 doStepFallingGear(Gear); |
6817 doStepFallingGear(Gear); |
6357 if (Gear^.Tag = 1) and (GameTicks and $FF = 0) and (hwRound(Gear^.X) < LongInt(leftX)) or (hwRound(Gear^.X) > LongInt(rightX)) or (hwRound(Gear^.Y) < LongInt(topY)) then |
6818 if (Gear^.Tag = 1) and (GameTicks and $FF = 0) and (hwRound(Gear^.X) < leftX) or (hwRound(Gear^.X) > rightX) or (hwRound(Gear^.Y) < topY) then |
6358 begin |
6819 begin |
6359 Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX); |
6820 Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX); |
6360 Gear^.Y:= int2hwFloat(GetRandom(LAND_HEIGHT-topY)+topY); |
6821 Gear^.Y:= int2hwFloat(GetRandom(LAND_HEIGHT-topY)+topY); |
6361 Gear^.dX:= _90-(GetRandomf*_360); |
6822 Gear^.dX:= _90-(GetRandomf*_360); |
6362 Gear^.dY:= _90-(GetRandomf*_360) |
6823 Gear^.dY:= _90-(GetRandomf*_360) |
6363 end; |
6824 end; |
6364 end |
6825 end |
6365 end; |
6826 end; |
6366 (* |
6827 |
6828 // TODO: Finish creeper implementation |
|
6367 procedure doStepCreeper(Gear: PGear); |
6829 procedure doStepCreeper(Gear: PGear); |
6368 var hogs: PGearArrayS; |
6830 var i,t,targDist,tmpDist: LongWord; |
6369 HHGear: PGear; |
6831 targ, tmpG: PGear; |
6370 tdX: hwFloat; |
6832 tX, tY: hwFloat; |
6371 dir: LongInt; |
6833 vg: PVisualGear; |
6372 begin |
6834 begin |
6373 doStepFallingGear(Gear); |
6835 targ:= nil; |
6374 if Gear^.Timer > 0 then dec(Gear^.Timer); |
6836 doStepFallingGear(Gear); |
6375 // creeper sleep phase |
6837 if (Gear^.State and gstFrozen) <> 0 then |
6376 if (Gear^.Hedgehog = nil) and (Gear^.Timer > 0) then exit; |
6838 begin |
6377 |
6839 if Gear^.Damage > 0 then |
6378 if Gear^.Hedgehog <> nil then HHGear:= Gear^.Hedgehog^.Gear |
6840 begin |
6379 else HHGear:= nil; |
6841 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
6380 |
6842 DeleteGear(Gear) |
6381 // creeper boom phase |
6843 end; |
6382 if (Gear^.State and gstTmpFlag <> 0) then |
|
6383 begin |
|
6384 if (Gear^.Timer = 0) then |
|
6385 begin |
|
6386 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 300, CurrentHedgehog, EXPLAutoSound); |
|
6387 DeleteGear(Gear) |
|
6388 end; |
|
6389 // ssssss he essssscaped |
|
6390 if (Gear^.Timer > 250) and ((HHGear = nil) or |
|
6391 (((abs(HHGear^.X.Round-Gear^.X.Round) + abs(HHGear^.Y.Round-Gear^.Y.Round) + 2) > 180) and |
|
6392 (Distance(HHGear^.X-Gear^.X,HHGear^.Y-Gear^.Y) > _180))) then |
|
6393 begin |
|
6394 Gear^.State:= Gear^.State and (not gstTmpFlag); |
|
6395 Gear^.Timer:= 0 |
|
6396 end; |
|
6397 exit |
|
6398 end; |
|
6399 |
|
6400 // Search out a new target, as target seek time has expired, target is dead, target is out of range, or we did not have a target |
|
6401 if (HHGear = nil) or (Gear^.Timer = 0) or |
|
6402 (((abs(HHGear^.X.Round-Gear^.X.Round) + abs(HHGear^.Y.Round-Gear^.Y.Round) + 2) > Gear^.Angle) and |
|
6403 (Distance(HHGear^.X-Gear^.X,HHGear^.Y-Gear^.Y) > int2hwFloat(Gear^.Angle))) |
|
6404 then |
|
6405 begin |
|
6406 hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Angle); |
|
6407 if hogs.size > 1 then |
|
6408 Gear^.Hedgehog:= hogs.ar^[GetRandom(hogs.size)]^.Hedgehog |
|
6409 else if hogs.size = 1 then Gear^.Hedgehog:= hogs.ar^[0]^.Hedgehog |
|
6410 else Gear^.Hedgehog:= nil; |
|
6411 if Gear^.Hedgehog <> nil then Gear^.Timer:= 5000; |
|
6412 exit |
|
6413 end; |
|
6414 |
|
6415 // we have a target. move the creeper. |
|
6416 if HHGear <> nil then |
|
6417 begin |
|
6418 // GOTCHA |
|
6419 if ((abs(HHGear^.X.Round-Gear^.X.Round) + abs(HHGear^.Y.Round-Gear^.Y.Round) + 2) < 50) and |
|
6420 (Distance(HHGear^.X-Gear^.X,HHGear^.Y-Gear^.Y) < _50) then |
|
6421 begin |
|
6422 // hisssssssssss |
|
6423 Gear^.State:= Gear^.State or gstTmpFlag; |
|
6424 Gear^.Timer:= 1500; |
|
6425 exit |
6844 exit |
6426 end; |
6845 end; |
6427 if (Gear^.State and gstMoving <> 0) then |
6846 if (TurnTimeLeft = 0) or (Gear^.Angle = 0) or (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.Gear = nil) then |
6428 begin |
6847 begin |
6429 Gear^.dY:= _0; |
6848 Gear^.Hedgehog:= nil; |
6430 Gear^.dX:= _0; |
6849 targ:= nil; |
6431 end |
6850 end |
6432 else if (GameTicks and $FF = 0) then |
6851 else if Gear^.Hedgehog <> nil then |
6433 begin |
6852 targ:= Gear^.Hedgehog^.Gear; |
6434 tdX:= HHGear^.X-Gear^.X; |
6853 if (targ <> nil) and ((GameTicks and $3F) = 0) and (TestCollisionYKick(Gear, 1) <> 0) then |
6435 dir:= hwSign(tdX); |
6854 begin |
6436 if TestCollisionX(Gear, dir) = 0 then |
6855 vg:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeWhite); |
6437 Gear^.X:= Gear^.X + signAs(_1,tdX); |
6856 if vg <> nil then vg^.Tint:= $FF0000FF; |
6438 if TestCollisionXwithXYShift(Gear, signAs(_10,tdX), 0, dir) <> 0 then |
6857 if (Gear^.X < targ^.X) then // need to add collision checks to avoid walking off edges or getting too close to obstacles where jumping is needed |
6439 begin |
6858 if (WorldEdge = weWrap) and ((targ^.X - Gear^.X) > ((Gear^.X - int2hwFloat(LeftX)) + (int2hwFloat(RightX) - targ^.X))) then |
6440 Gear^.dX:= SignAs(_0_15, tdX); |
6859 Gear^.dX:= -cLittle |
6441 Gear^.dY:= -_0_3; |
6860 else |
6442 Gear^.State:= Gear^.State or gstMoving |
6861 Gear^.dX:= cLittle |
6862 else if (Gear^.X > targ^.X) then |
|
6863 if (WorldEdge = weWrap) and ((Gear^.X - targ^.X) > ((targ^.X - int2hwFloat(LeftX)) + (int2hwFloat(RightX) - Gear^.X))) then |
|
6864 Gear^.dX:= cLittle |
|
6865 else |
|
6866 Gear^.dX:= -cLittle; |
|
6867 if (GetRandom(30) = 0) then |
|
6868 begin |
|
6869 Gear^.dY := -_0_15; |
|
6870 Gear^.dX:= SignAs(_0_15, Gear^.dX); |
|
6871 end; |
|
6872 MakeHedgehogsStep(Gear); |
|
6873 end; |
|
6874 if (TurnTimeLeft = 0) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then |
|
6875 AllInactive := false; |
|
6876 |
|
6877 if targ <> nil then |
|
6878 begin |
|
6879 tX:=Gear^.X-targ^.X; |
|
6880 tY:=Gear^.Y-targ^.Y; |
|
6881 // allow escaping - should maybe flag this too |
|
6882 if (GameTicks > Gear^.FlightTime+10000) or |
|
6883 ((tX.Round+tY.Round > Gear^.Angle*6) and |
|
6884 (hwRound(hwSqr(tX) + hwSqr(tY)) > sqr(Gear^.Angle*6))) then |
|
6885 targ:= nil |
|
6886 end; |
|
6887 |
|
6888 // If in ready timer, or after turn, or in first 5 seconds of turn (really a window due to extra time utility) |
|
6889 // or mine is inactive due to lack of gsttmpflag or hunting is disabled due to seek radius of 0 |
|
6890 // then we aren't hunting |
|
6891 if (ReadyTimeLeft > 0) or (TurnTimeLeft = 0) or |
|
6892 ((TurnTimeLeft < cHedgehogTurnTime) and (cHedgehogTurnTime-TurnTimeLeft < 5000)) or |
|
6893 (Gear^.State and gsttmpFlag = 0) or |
|
6894 (Gear^.Angle = 0) then |
|
6895 gear^.State:= gear^.State and (not gstChooseTarget) |
|
6896 else if |
|
6897 // todo, allow not finding new target, set timeout on target retention |
|
6898 (Gear^.State and gstAttacking = 0) and |
|
6899 ((GameTicks and $FF) = 17) and |
|
6900 (GameTicks > Gear^.FlightTime) then // recheck hunted hog |
|
6901 begin |
|
6902 gear^.State:= gear^.State or gstChooseTarget; |
|
6903 if targ <> nil then |
|
6904 targDist:= Distance(Gear^.X-targ^.X,Gear^.Y-targ^.Y).Round |
|
6905 else targDist:= 0; |
|
6906 for t:= 0 to Pred(TeamsCount) do |
|
6907 with TeamsArray[t]^ do |
|
6908 for i:= 0 to cMaxHHIndex do |
|
6909 if Hedgehogs[i].Gear <> nil then |
|
6910 begin |
|
6911 tmpG:= Hedgehogs[i].Gear; |
|
6912 tX:=Gear^.X-tmpG^.X; |
|
6913 tY:=Gear^.Y-tmpG^.Y; |
|
6914 if (Gear^.Angle = $FFFFFFFF) or |
|
6915 ((tX.Round+tY.Round < Gear^.Angle) and |
|
6916 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Angle))) then |
|
6917 begin |
|
6918 if targ <> nil then tmpDist:= Distance(tX,tY).Round; |
|
6919 if (targ = nil) or (tmpDist < targDist) then |
|
6920 begin |
|
6921 if targ = nil then targDist:= Distance(tX,tY).Round |
|
6922 else targDist:= tmpDist; |
|
6923 Gear^.Hedgehog:= @Hedgehogs[i]; |
|
6924 targ:= tmpG; |
|
6925 end |
|
6926 end |
|
6927 end; |
|
6928 if targ <> nil then Gear^.FlightTime:= GameTicks + 5000 |
|
6929 end; |
|
6930 |
|
6931 if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then |
|
6932 begin |
|
6933 if ((Gear^.State and gstAttacking) = 0) then |
|
6934 begin |
|
6935 if ((GameTicks and $1F) = 0) then |
|
6936 begin |
|
6937 if targ <> nil then |
|
6938 begin |
|
6939 tX:=Gear^.X-targ^.X; |
|
6940 tY:=Gear^.Y-targ^.Y; |
|
6941 if (tX.Round+tY.Round < Gear^.Boom) and |
|
6942 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then |
|
6943 Gear^.State := Gear^.State or gstAttacking |
|
6944 end |
|
6945 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then |
|
6946 Gear^.State := Gear^.State or gstAttacking |
|
6947 end |
|
6443 end |
6948 end |
6444 end; |
6949 else // gstAttacking <> 0 |
6445 end; |
6950 begin |
6446 end; |
6951 AllInactive := false; |
6447 *) |
6952 if (Gear^.Timer and $1FF) = 0 then |
6953 PlaySound(sndVaporize); |
|
6954 if Gear^.Timer = 0 then |
|
6955 begin |
|
6956 // recheck |
|
6957 if targ <> nil then |
|
6958 begin |
|
6959 tX:=Gear^.X-targ^.X; |
|
6960 tY:=Gear^.Y-targ^.Y; |
|
6961 if (tX.Round+tY.Round < Gear^.Boom) and |
|
6962 (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then |
|
6963 begin |
|
6964 Gear^.Hedgehog:= CurrentHedgehog; |
|
6965 tmpG:= FollowGear; |
|
6966 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
6967 FollowGear:= tmpG; |
|
6968 DeleteGear(Gear); |
|
6969 exit |
|
6970 end |
|
6971 end |
|
6972 else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then |
|
6973 begin |
|
6974 Gear^.Hedgehog:= CurrentHedgehog; |
|
6975 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
6976 DeleteGear(Gear); |
|
6977 exit |
|
6978 end; |
|
6979 Gear^.State:= Gear^.State and (not gstAttacking); |
|
6980 Gear^.Timer:= Gear^.WDTimer |
|
6981 end; |
|
6982 if Gear^.Timer > 0 then |
|
6983 dec(Gear^.Timer); |
|
6984 end |
|
6985 end |
|
6986 else // gsttmpFlag = 0 |
|
6987 if (TurnTimeLeft = 0) |
|
6988 or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) |
|
6989 or (CurrentHedgehog^.Gear = nil) then |
|
6990 begin |
|
6991 Gear^.FlightTime:= GameTicks; |
|
6992 Gear^.State := Gear^.State or gsttmpFlag |
|
6993 end |
|
6994 end; |
|
6995 |
|
6448 //////////////////////////////////////////////////////////////////////////////// |
6996 //////////////////////////////////////////////////////////////////////////////// |
6449 procedure doStepKnife(Gear: PGear); |
6997 procedure doStepKnife(Gear: PGear); |
6450 //var ox, oy: LongInt; |
|
6451 // la: hwFloat; |
|
6452 var a: real; |
6998 var a: real; |
6453 begin |
6999 begin |
6454 // Gear is shrunk so it can actually escape the hog without carving into the terrain |
7000 // Gear is shrunk so it can actually escape the hog without carving into the terrain |
6455 if (Gear^.Radius = 4) and (Gear^.CollisionMask = $FFFF) then Gear^.Radius:= 7; |
7001 if (Gear^.Radius = 4) and (Gear^.CollisionMask = lfAll) then Gear^.Radius:= 7; |
6456 if Gear^.Damage > 100 then Gear^.CollisionMask:= 0 |
7002 if Gear^.Damage > 100 then Gear^.CollisionMask:= 0 |
6457 else if Gear^.Damage > 30 then |
7003 else if Gear^.Damage > 30 then |
6458 if GetRandom(max(4,18-Gear^.Damage div 10)) < 3 then Gear^.CollisionMask:= 0; |
7004 if GetRandom(max(4,18-Gear^.Damage div 10)) < 3 then Gear^.CollisionMask:= 0; |
6459 Gear^.Damage:= 0; |
7005 Gear^.Damage:= 0; |
6460 if Gear^.Timer > 0 then dec(Gear^.Timer); |
7006 if Gear^.Timer > 0 then dec(Gear^.Timer); |
6470 CalcRotationDirAngle(Gear); |
7016 CalcRotationDirAngle(Gear); |
6471 Gear^.DirAngle:= a+(Gear^.DirAngle-a)*2*hwSign(Gear^.dX) // double rotation |
7017 Gear^.DirAngle:= a+(Gear^.DirAngle-a)*2*hwSign(Gear^.dX) // double rotation |
6472 end |
7018 end |
6473 else if (Gear^.CollisionIndex = -1) and (Gear^.Timer = 0) then |
7019 else if (Gear^.CollisionIndex = -1) and (Gear^.Timer = 0) then |
6474 begin |
7020 begin |
6475 (*ox:= 0; oy:= 0; |
|
6476 if TestCollisionYwithGear(Gear, -1) <> 0 then oy:= -1; |
|
6477 if TestCollisionXwithGear(Gear, 1) <> 0 then ox:= 1; |
|
6478 if TestCollisionXwithGear(Gear, -1) <> 0 then ox:= -1; |
|
6479 if TestCollisionYwithGear(Gear, 1) <> 0 then oy:= 1; |
|
6480 |
|
6481 la:= _10000; |
|
6482 if (ox <> 0) or (oy <> 0) then |
|
6483 la:= CalcSlopeNearGear(Gear, ox, oy); |
|
6484 if la = _10000 then |
|
6485 begin |
|
6486 // debug for when we couldn't get an angle |
|
6487 //AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeWhite); |
|
6488 *) |
|
6489 if Gear^.Health > 0 then |
7021 if Gear^.Health > 0 then |
6490 PlaySound(Gear^.ImpactSound); |
7022 PlaySound(Gear^.ImpactSound); |
6491 |
7023 |
6492 Gear^.DirAngle:= DxDy2Angle(Gear^.dX, Gear^.dY) + (random(30)-15); |
7024 Gear^.DirAngle:= DxDy2Angle(Gear^.dX, Gear^.dY) + (random(30)-15); |
6493 if (Gear^.dX.isNegative and Gear^.dY.isNegative) or |
7025 if (Gear^.dX.isNegative and Gear^.dY.isNegative) or |
6494 ((not Gear^.dX.isNegative) and (not Gear^.dY.isNegative)) then Gear^.DirAngle:= Gear^.DirAngle-90; |
7026 ((not Gear^.dX.isNegative) and (not Gear^.dY.isNegative)) then Gear^.DirAngle:= Gear^.DirAngle-90; |
6495 // end |
|
6496 // else Gear^.DirAngle:= hwFloat2Float(la)*90; // sheepluva's comment claims 45deg = 0.5 - yet orientation doesn't seem consistent? |
|
6497 // AddFileLog('la: '+floattostr(la)+' DirAngle: '+inttostr(round(Gear^.DirAngle))); |
|
6498 Gear^.dX:= _0; |
7027 Gear^.dX:= _0; |
6499 Gear^.dY:= _0; |
7028 Gear^.dY:= _0; |
6500 Gear^.State:= Gear^.State and (not gstMoving) or gstCollision; |
7029 Gear^.State:= Gear^.State and (not gstMoving) or gstCollision; |
6501 Gear^.Radius:= 16; |
7030 Gear^.Radius:= 16; |
6502 if Gear^.Health > 0 then AmmoShove(Gear, Gear^.Health, 0); |
7031 if Gear^.Health > 0 then AmmoShove(Gear, Gear^.Health, 0); |
6512 and (TestCollisionYwithGear(Gear, 1) = 0) then Gear^.State:= Gear^.State and (not gstCollision) or gstMoving; |
7041 and (TestCollisionYwithGear(Gear, 1) = 0) then Gear^.State:= Gear^.State and (not gstCollision) or gstMoving; |
6513 end |
7042 end |
6514 end; |
7043 end; |
6515 |
7044 |
6516 //////////////////////////////////////////////////////////////////////////////// |
7045 //////////////////////////////////////////////////////////////////////////////// |
6517 procedure doStepDuck(Gear: PGear); |
|
6518 begin |
|
6519 // Mirror duck on bounce world edge, even turn around later |
|
6520 if WorldWrap(Gear) and (WorldEdge = weBounce) then |
|
6521 begin |
|
6522 Gear^.Tag:= Gear^.Tag * -1; |
|
6523 if Gear^.Pos = 2 then |
|
6524 Gear^.Pos:= 1 |
|
6525 else if Gear^.Pos = 1 then |
|
6526 Gear^.Pos:= 2 |
|
6527 else if Gear^.Pos = 5 then |
|
6528 Gear^.Pos:= 6 |
|
6529 else if Gear^.Pos = 5 then |
|
6530 Gear^.Pos:= 5; |
|
6531 end; |
|
6532 |
|
6533 AllInactive := false; |
|
6534 |
|
6535 // Duck falls (Pos = 0) |
|
6536 if Gear^.Pos = 0 then |
|
6537 doStepFallingGear(Gear); |
|
6538 |
|
6539 (* Check if duck is near water surface |
|
6540 (Karma is distance from water) *) |
|
6541 if (Gear^.Pos <> 1) and (Gear^.Pos <> 2) and (cWaterLine <= hwRound(Gear^.Y) + Gear^.Karma) then |
|
6542 begin |
|
6543 if cWaterLine = hwRound(Gear^.Y) + Gear^.Karma then |
|
6544 begin |
|
6545 // Let's make that duck swim! |
|
6546 // Does the duck come FROM the Sea edge? (left or right) |
|
6547 if (((Gear^.Pos = 3) or (Gear^.Pos = 7)) and (cWindSpeed > _0)) or (((Gear^.Pos = 4) or (Gear^.Pos = 8)) and (cWindSpeed < _0)) then |
|
6548 begin |
|
6549 PlaySound(sndDuckWater); |
|
6550 Gear^.DirAngle:= 0; |
|
6551 Gear^.Pos:= 1; |
|
6552 Gear^.dY:= _0; |
|
6553 end; |
|
6554 |
|
6555 // Duck comes either falling (usual case) or was rising from below |
|
6556 if (Gear^.Pos = 0) or (Gear^.Pos = 5) or (Gear^.Pos = 6) then |
|
6557 begin |
|
6558 PlaySound(sndDroplet2); |
|
6559 if Gear^.dY > _0_4 then |
|
6560 PlaySound(sndDuckWater); |
|
6561 Gear^.Pos:= 1; |
|
6562 Gear^.dY:= _0; |
|
6563 end; |
|
6564 end |
|
6565 else if Gear^.Pos = 0 then |
|
6566 Gear^.Pos:= 5; |
|
6567 end; |
|
6568 |
|
6569 // Manual speed handling when duck is on water |
|
6570 if Gear^.Pos <> 0 then |
|
6571 begin |
|
6572 Gear^.X:= Gear^.X + Gear^.dX; |
|
6573 Gear^.Y:= Gear^.Y + Gear^.dY; |
|
6574 end; |
|
6575 |
|
6576 // Handle speed |
|
6577 // 1-4: On water: Let's swim! |
|
6578 if Gear^.Pos = 1 then |
|
6579 // On water (normal) |
|
6580 Gear^.dX:= cWindSpeed * Gear^.Damage |
|
6581 else if Gear^.Pos = 2 then |
|
6582 // On water, mirrored (after bounce edge bounce) |
|
6583 Gear^.dX:= -cWindSpeed * Gear^.Damage |
|
6584 else if Gear^.Pos = 3 then |
|
6585 // On left Sea edge |
|
6586 Gear^.dY:= cWindSpeed * Gear^.Damage |
|
6587 else if Gear^.Pos = 4 then |
|
6588 // On right Sea edge |
|
6589 Gear^.dY:= -cWindSpeed * Gear^.Damage |
|
6590 // 5-8: Underwater: Slowly rise to the surface and slightly follow wind |
|
6591 else if Gear^.Pos = 5 then |
|
6592 // Underwater (normal) |
|
6593 begin |
|
6594 Gear^.dX:= (cWindSpeed / 4) * Gear^.Damage; |
|
6595 Gear^.dY:= -_0_07; |
|
6596 end |
|
6597 else if Gear^.Pos = 6 then |
|
6598 // Underwater, mirrored duck (after bounce edge bounce) |
|
6599 begin |
|
6600 Gear^.dX:= -(cWindSpeed / 4) * Gear^.Damage; |
|
6601 Gear^.dY:= -_0_07; |
|
6602 end |
|
6603 else if Gear^.Pos = 7 then |
|
6604 // Inside left Sea edge |
|
6605 begin |
|
6606 Gear^.dX:= _0_07; |
|
6607 Gear^.dY:= (cWindSpeed / 4) * Gear^.Damage; |
|
6608 end |
|
6609 else if Gear^.Pos = 8 then |
|
6610 // Inside right Sea edge |
|
6611 begin |
|
6612 Gear^.dX:= -_0_07; |
|
6613 Gear^.dY:= -(cWindSpeed / 4) * Gear^.Damage; |
|
6614 end; |
|
6615 |
|
6616 |
|
6617 // Rotate duck and change direction when reaching Sea world edge (Pos 3 or 4) |
|
6618 if (WorldEdge = weSea) and (Gear^.Pos <> 3) and (Gear^.Pos <> 4) then |
|
6619 // Swimming TOWARDS left edge |
|
6620 if (LeftX >= hwRound(Gear^.X) - Gear^.Karma) and ((cWindSpeed < _0) or ((Gear^.Pos = 0) or (Gear^.Pos = 7))) then |
|
6621 begin |
|
6622 // Turn duck when reaching edge the first time |
|
6623 if (Gear^.Pos <> 3) and (Gear^.Pos <> 7) then |
|
6624 begin |
|
6625 if Gear^.Tag = 1 then |
|
6626 Gear^.DirAngle:= 90 |
|
6627 else |
|
6628 Gear^.DirAngle:= 270; |
|
6629 end; |
|
6630 |
|
6631 // Reaching the edge surface |
|
6632 if (LeftX = hwRound(Gear^.X) - Gear^.Karma) and (Gear^.Pos <> 3) then |
|
6633 // We are coming from the horizontal side |
|
6634 begin |
|
6635 PlaySound(sndDuckWater); |
|
6636 Gear^.dX:= _0; |
|
6637 Gear^.Pos:= 3; |
|
6638 end |
|
6639 else |
|
6640 // We are coming from inside the Sea, go into “surfacing” mode |
|
6641 Gear^.Pos:= 7; |
|
6642 |
|
6643 end |
|
6644 |
|
6645 // Swimming TOWARDS right edge (similar to left edge) |
|
6646 else if (RightX <= hwRound(Gear^.X) + Gear^.Karma) and ((cWindSpeed > _0) or ((Gear^.Pos = 0) or (Gear^.Pos = 8))) then |
|
6647 begin |
|
6648 if (Gear^.Pos <> 4) and (Gear^.Pos <> 8) then |
|
6649 begin |
|
6650 if Gear^.Tag = 1 then |
|
6651 Gear^.DirAngle:= 270 |
|
6652 else |
|
6653 Gear^.DirAngle:= 90; |
|
6654 end; |
|
6655 |
|
6656 if (RightX = hwRound(Gear^.X) + Gear^.Karma) and (Gear^.Pos <> 4) then |
|
6657 begin |
|
6658 PlaySound(sndDuckWater); |
|
6659 Gear^.dX:= _0; |
|
6660 Gear^.Pos:= 4; |
|
6661 end |
|
6662 else |
|
6663 Gear^.Pos:= 8; |
|
6664 |
|
6665 end; |
|
6666 |
|
6667 |
|
6668 if Gear^.Pos <> 0 then |
|
6669 // Manual collision check required because we don't use onStepFallingGear in this case |
|
6670 CheckCollision(Gear); |
|
6671 if (Gear^.Timer = 0) or ((Gear^.State and gstCollision) <> 0) then |
|
6672 // Explode duck |
|
6673 begin |
|
6674 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound); |
|
6675 PlaySound(sndDuckDie); |
|
6676 DeleteGear(Gear); |
|
6677 exit; |
|
6678 end; |
|
6679 |
|
6680 // Update timer stuff |
|
6681 if Gear^.Timer < 6000 then |
|
6682 Gear^.RenderTimer:= true |
|
6683 else |
|
6684 Gear^.RenderTimer:= false; |
|
6685 |
|
6686 dec(Gear^.Timer); |
|
6687 end; |
|
6688 |
|
6689 //////////////////////////////////////////////////////////////////////////////// |
|
6690 procedure doStepMinigunWork(Gear: PGear); |
7046 procedure doStepMinigunWork(Gear: PGear); |
6691 var HHGear: PGear; |
7047 var HHGear: PGear; |
6692 bullet: PGear; |
7048 bullet: PGear; |
6693 rx, ry: hwFloat; |
7049 rx, ry: hwFloat; |
6694 gX, gY: LongInt; |
7050 gX, gY: LongInt; |
6713 gY := hwRound(Gear^.Y) + GetLaunchY(amMinigun, HHGear^.Angle); |
7069 gY := hwRound(Gear^.Y) + GetLaunchY(amMinigun, HHGear^.Angle); |
6714 rx := rndSign(getRandomf * _0_2); |
7070 rx := rndSign(getRandomf * _0_2); |
6715 ry := rndSign(getRandomf * _0_2); |
7071 ry := rndSign(getRandomf * _0_2); |
6716 |
7072 |
6717 bullet:= AddGear(gx, gy, gtMinigunBullet, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0); |
7073 bullet:= AddGear(gx, gy, gtMinigunBullet, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0); |
6718 bullet^.CollisionMask:= lfNotCurrentMask; |
7074 bullet^.CollisionMask:= lfNotCurHogCrate; |
6719 bullet^.WDTimer := Gear^.WDTimer; |
7075 bullet^.WDTimer := Gear^.WDTimer; |
6720 Inc(Gear^.WDTimer); |
7076 Inc(Gear^.WDTimer); |
6721 |
7077 |
6722 CreateShellForGear(Gear, Gear^.Tag and 1); |
7078 CreateShellForGear(Gear, Gear^.Tag and 1); |
6723 end; |
7079 end; |
6767 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
7123 Gear^.Y := Gear^.Y + Gear^.dY * 2; |
6768 Gear^.FlightTime := 0; |
7124 Gear^.FlightTime := 0; |
6769 Gear^.doStep := @doStepBulletWork |
7125 Gear^.doStep := @doStepBulletWork |
6770 end; |
7126 end; |
6771 |
7127 |
6772 (* |
|
6773 This didn't end up getting used, but, who knows, might be reasonable for javellin or something |
|
6774 // Make the knife initial angle based on the hog attack angle, or is that too hard? |
|
6775 procedure doStepKnife(Gear: PGear); |
|
6776 var t, |
|
6777 gx, gy, ga, // gear x,y,angle |
|
6778 lx, ly, la, // land x,y,angle |
|
6779 ox, oy, // x,y offset |
|
6780 w, h, // wXh of clip area |
|
6781 tx, ty // tip position in sprite |
|
6782 : LongInt; |
|
6783 surf: PSDL_Surface; |
|
6784 s: hwFloat; |
|
6785 |
|
6786 begin |
|
6787 Gear^.dY := Gear^.dY + cGravity; |
|
6788 if (GameFlags and gfMoreWind) <> 0 then |
|
6789 Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density; |
|
6790 Gear^.X := Gear^.X + Gear^.dX; |
|
6791 Gear^.Y := Gear^.Y + Gear^.dY; |
|
6792 CheckGearDrowning(Gear); |
|
6793 gx:= hwRound(Gear^.X); |
|
6794 gy:= hwRound(Gear^.Y); |
|
6795 if Gear^.State and gstDrowning <> 0 then exit; |
|
6796 with Gear^ do |
|
6797 begin |
|
6798 if CheckLandValue(gx, gy, lfLandMask) then |
|
6799 begin |
|
6800 t:= Angle + hwRound((hwAbs(dX)+hwAbs(dY)) * _10); |
|
6801 |
|
6802 if t < 0 then inc(t, 4096) |
|
6803 else if 4095 < t then dec(t, 4096); |
|
6804 Angle:= t; |
|
6805 |
|
6806 DirAngle:= Angle / 4096 * 360 |
|
6807 end |
|
6808 else |
|
6809 begin |
|
6810 //This is the set of postions for the knife. |
|
6811 //Using FlipSurface and copyToXY the knife can be written to the LandPixels at 32 positions, and an appropriate line drawn in Land. |
|
6812 t:= Angle mod 1024; |
|
6813 case t div 128 of |
|
6814 0: begin |
|
6815 ox:= 2; oy:= 5; |
|
6816 w := 25; h:= 5; |
|
6817 tx:= 0; ty:= 2 |
|
6818 end; |
|
6819 1: begin |
|
6820 ox:= 2; oy:= 15; |
|
6821 w:= 24; h:= 8; |
|
6822 tx:= 0; ty:= 7 |
|
6823 end; |
|
6824 2: begin |
|
6825 ox:= 2; oy:= 27; |
|
6826 w:= 23; h:= 12; |
|
6827 tx:= -12; ty:= -5 |
|
6828 end; |
|
6829 3: begin |
|
6830 ox:= 2; oy:= 43; |
|
6831 w:= 21; h:= 15; |
|
6832 tx:= 0; ty:= 14 |
|
6833 end; |
|
6834 4: begin |
|
6835 ox:= 29; oy:= 8; |
|
6836 w:= 19; h:= 19; |
|
6837 tx:= 0; ty:= 17 |
|
6838 end; |
|
6839 5: begin |
|
6840 ox:= 29; oy:= 32; |
|
6841 w:= 15; h:= 21; |
|
6842 tx:= 0; ty:= 20 |
|
6843 end; |
|
6844 6: begin |
|
6845 ox:= 51; oy:= 3; |
|
6846 w:= 11; h:= 23; |
|
6847 tx:= 0; ty:= 22 |
|
6848 end; |
|
6849 7: begin |
|
6850 ox:= 51; oy:= 34; |
|
6851 w:= 7; h:= 24; |
|
6852 tx:= 0; ty:= 23 |
|
6853 end |
|
6854 end; |
|
6855 |
|
6856 surf:= SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, RMask, GMask, BMask, AMask); |
|
6857 copyToXYFromRect(SpritesData[sprKnife].Surface, surf, ox, oy, w, h, 0, 0); |
|
6858 // try to make the knife hit point first |
|
6859 lx := 0; |
|
6860 ly := 0; |
|
6861 if CalcSlopeTangent(Gear, gx, gy, lx, ly, 255) then |
|
6862 begin |
|
6863 la:= vector2Angle(int2hwFloat(lx), int2hwFloat(ly)); |
|
6864 ga:= vector2Angle(dX, dY); |
|
6865 AddFileLog('la: '+inttostr(la)+' ga: '+inttostr(ga)+' Angle: '+inttostr(Angle)); |
|
6866 // change to 0 to 4096 forced by LongWord in Gear |
|
6867 if la < 0 then la:= 4096+la; |
|
6868 if ga < 0 then ga:= 4096+ga; |
|
6869 if ((Angle > ga) and (Angle < la)) or ((Angle < ga) and (Angle > la)) then |
|
6870 begin |
|
6871 if Angle >= 2048 then dec(Angle, 2048) |
|
6872 else if Angle < 2048 then inc(Angle, 2048) |
|
6873 end; |
|
6874 AddFileLog('la: '+inttostr(la)+' ga: '+inttostr(ga)+' Angle: '+inttostr(Angle)) |
|
6875 end; |
|
6876 case Angle div 1024 of |
|
6877 0: begin |
|
6878 flipSurface(surf, true); |
|
6879 flipSurface(surf, true); |
|
6880 BlitImageAndGenerateCollisionInfo(gx-(w-tx), gy-(h-ty), w, surf) |
|
6881 end; |
|
6882 1: begin |
|
6883 flipSurface(surf, false); |
|
6884 BlitImageAndGenerateCollisionInfo(gx-(w-tx), gy-ty, w, surf) |
|
6885 end; |
|
6886 2: begin // knife was actually drawn facing this way... |
|
6887 BlitImageAndGenerateCollisionInfo(gx-tx, gy-ty, w, surf) |
|
6888 end; |
|
6889 3: begin |
|
6890 flipSurface(surf, true); |
|
6891 BlitImageAndGenerateCollisionInfo(gx-tx, gy-(h-ty), w, surf) |
|
6892 end |
|
6893 end; |
|
6894 SDL_FreeSurface(surf); |
|
6895 // this needs to calculate actual width/height + land clipping since update texture doesn't. |
|
6896 // i.e. this will crash if you fire near sides of map, but until I get the blit right, not going to put real values |
|
6897 UpdateLandTexture(hwRound(X)-32, 64, hwRound(Y)-32, 64, true); |
|
6898 DeleteGear(Gear); |
|
6899 exit |
|
6900 end |
|
6901 end; |
|
6902 end; |
|
6903 *) |
|
6904 |
|
6905 end. |
7128 end. |