355 Gear^.DirAngle := Gear^.DirAngle + 360 |
355 Gear^.DirAngle := Gear^.DirAngle + 360 |
356 else if 360 < Gear^.DirAngle then |
356 else if 360 < Gear^.DirAngle then |
357 Gear^.DirAngle := Gear^.DirAngle - 360 |
357 Gear^.DirAngle := Gear^.DirAngle - 360 |
358 end; |
358 end; |
359 |
359 |
|
360 procedure DrownGear(Gear: PGear); |
|
361 begin |
|
362 Gear^.doStep := @doStepDrowningGear; |
|
363 |
|
364 Gear^.Timer := 5000; // how long game should wait |
|
365 end; |
|
366 |
360 function CheckGearDrowning(var Gear: PGear): boolean; |
367 function CheckGearDrowning(var Gear: PGear): boolean; |
361 var |
368 var |
362 skipSpeed, skipAngle, skipDecay: hwFloat; |
369 skipSpeed, skipAngle, skipDecay, hwTmp: hwFloat; |
363 i, maxDrops, X, Y: LongInt; |
370 i, maxDrops, X, Y, dist2Water: LongInt; |
364 vdX, vdY: real; |
371 vdX, vdY, tmp: real; |
365 particle, splash: PVisualGear; |
372 particle, splash: PVisualGear; |
366 isSubmersible: boolean; |
373 isSubmersible, isImpactH, isImpactRight, isLeaving: boolean; |
367 s: ansistring; |
374 s: ansistring; |
368 begin |
375 begin |
369 // probably needs tweaking. might need to be in a case statement based upon gear type |
376 // probably needs tweaking. might need to be in a case statement based upon gear type |
|
377 X:= hwRound(Gear^.X); |
370 Y:= hwRound(Gear^.Y); |
378 Y:= hwRound(Gear^.Y); |
371 if cWaterLine < Y + Gear^.Radius then |
379 |
372 begin |
380 dist2Water:= cWaterLine - (Y + Gear^.Radius); |
|
381 isImpactH:= false; |
|
382 |
|
383 if WorldEdge = weSea then |
|
384 begin |
|
385 i:= dist2Water; |
|
386 dist2Water:= min(dist2Water, min(X - Gear^.Radius - leftX, rightX - (X + Gear^.Radius))); |
|
387 isImpactH:= i <> dist2Water; |
|
388 end; |
|
389 |
|
390 if dist2Water < 0 then |
|
391 begin |
|
392 // invisible gears will just be deleted |
|
393 // unless they are generic fallers, then they will be "respawned" |
373 if Gear^.State and gstInvisible <> 0 then |
394 if Gear^.State and gstInvisible <> 0 then |
374 begin |
395 begin |
375 if Gear^.Kind = gtGenericFaller then |
396 if Gear^.Kind = gtGenericFaller then |
376 begin |
397 begin |
377 Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX); |
398 Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX); |
384 end; |
405 end; |
385 isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0); |
406 isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0); |
386 skipSpeed := _0_25; |
407 skipSpeed := _0_25; |
387 skipAngle := _1_9; |
408 skipAngle := _1_9; |
388 skipDecay := _0_87; |
409 skipDecay := _0_87; |
389 X:= hwRound(Gear^.X); |
410 vdX:= abs(hwFloat2Float(Gear^.dX)); |
390 vdX:= hwFloat2Float(Gear^.dX); |
411 vdY:= abs(hwFloat2Float(Gear^.dY)); |
391 vdY:= hwFloat2Float(Gear^.dY); |
412 |
392 // this could perhaps be a tiny bit higher. |
413 // skipping |
393 if (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) |
414 |
394 and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then |
415 // check for -1 depth because if deeper, then it already had its chance of skipping |
|
416 if (dist2Water = -1) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) |
|
417 and ( ((not isImpactH) and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY))) |
|
418 or (isImpactH and (hwAbs(Gear^.dY) > skipAngle * hwAbs(Gear^.dX))) ) then |
395 begin |
419 begin |
396 Gear^.dY.isNegative := true; |
420 // if skipping we move the gear out of water |
|
421 if isImpactH then |
|
422 begin |
|
423 Gear^.dX.isNegative := (not Gear^.dX.isNegative); |
|
424 Gear^.X:= Gear^.X + Gear^.dX; |
|
425 end |
|
426 else |
|
427 begin |
|
428 Gear^.dY.isNegative := (not Gear^.dY.isNegative); |
|
429 Gear^.Y:= Gear^.Y + Gear^.dY; |
|
430 end; |
397 Gear^.dY := Gear^.dY * skipDecay; |
431 Gear^.dY := Gear^.dY * skipDecay; |
398 Gear^.dX := Gear^.dX * skipDecay; |
432 Gear^.dX := Gear^.dX * skipDecay; |
399 CheckGearDrowning := false; |
433 CheckGearDrowning := false; |
400 PlaySound(sndSkip) |
434 PlaySound(sndSkip) |
401 end |
435 end |
402 else |
436 else // not skipping |
403 begin |
437 begin |
404 if not isSubmersible then |
438 if not isSubmersible then |
405 begin |
439 begin |
406 CheckGearDrowning := true; |
440 CheckGearDrowning := true; |
407 Gear^.State := gstDrowning; |
441 Gear^.State := gstDrowning; |
416 ResurrectHedgehog(Gear); |
450 ResurrectHedgehog(Gear); |
417 exit(true) |
451 exit(true) |
418 end |
452 end |
419 else |
453 else |
420 begin |
454 begin |
421 Gear^.doStep := @doStepDrowningGear; |
455 DrownGear(Gear); |
422 Gear^.State := Gear^.State and (not gstHHDriven); |
456 Gear^.State := Gear^.State and (not gstHHDriven); |
423 s:= ansistring(Gear^.Hedgehog^.Name); |
457 s:= ansistring(Gear^.Hedgehog^.Name); |
424 AddCaption(FormatA(GetEventString(eidDrowned), s), cWhiteColor, capgrpMessage); |
458 AddCaption(FormatA(GetEventString(eidDrowned), s), cWhiteColor, capgrpMessage); |
425 end |
459 end |
426 end |
460 end |
427 else |
461 else |
428 Gear^.doStep := @doStepDrowningGear; |
462 DrownGear(Gear); |
429 if Gear^.Kind = gtFlake then |
463 if Gear^.Kind = gtFlake then |
430 exit(true) // skip splashes |
464 exit(true); // skip splashes |
431 end |
465 end |
|
466 // drown submersible grears if far below map |
432 else if (Y > cWaterLine + cVisibleWater*4) and |
467 else if (Y > cWaterLine + cVisibleWater*4) and |
433 ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then |
468 ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then |
434 Gear^.doStep:= @doStepDrowningGear; |
469 DrownGear(Gear); |
435 if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
470 |
436 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
471 isImpactRight:= isImpactH and (abs(X - leftX) > abs(rightX - X)); |
437 and (CurAmmoGear^.dY < _0_01))) then |
472 isLeaving:= (isSubmersible and (dist2Water = -2 * Gear^.Radius) and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) |
438 if Gear^.Density * Gear^.dY > _1 then |
473 and (((not isImpactH) and CurAmmoGear^.dY.isNegative) or (isImpactH and (isImpactRight = CurAmmoGear^.dX.isNegative)))); |
|
474 |
|
475 // splash sound |
|
476 |
|
477 if ((not isSubmersible) and (dist2Water = -1)) |
|
478 or isLeaving then |
|
479 begin |
|
480 // adjust water impact sound on gear speed and density |
|
481 if isImpactH then |
|
482 hwTmp:= hwAbs(Gear^.Density * Gear^.dX) |
|
483 else |
|
484 hwTmp:= hwAbs(Gear^.Density * Gear^.dY); |
|
485 |
|
486 if hwTmp > _1 then |
439 PlaySound(sndSplash) |
487 PlaySound(sndSplash) |
440 else if Gear^.Density * Gear^.dY > _0_5 then |
488 else if hwTmp > _0_5 then |
441 PlaySound(sndSkip) |
489 PlaySound(sndSkip) |
442 else |
490 else |
443 PlaySound(sndDroplet2); |
491 PlaySound(sndDroplet2); |
|
492 end; |
444 end; |
493 end; |
445 |
494 |
|
495 // splash animation |
|
496 |
446 if ((cReducedQuality and rqPlainSplash) = 0) |
497 if ((cReducedQuality and rqPlainSplash) = 0) |
447 and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius)) |
498 and (((not isSubmersible) and (dist2Water = -1)) |
448 or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0) |
499 or isLeaving) then |
449 and (CurAmmoGear^.dY < _0_01)))) then |
|
450 begin |
500 begin |
451 splash:= AddVisualGear(X, cWaterLine, vgtSplash); |
501 splash:= AddVisualGear(X, Y, vgtSplash); |
452 if splash <> nil then |
502 if splash <> nil then |
|
503 begin |
|
504 if isImpactH then |
|
505 begin |
|
506 splash^.Scale:= abs(hwFloat2Float((Gear^.Density / _3) * Gear^.dX)); |
|
507 if isImpactRight then |
|
508 splash^.Angle:= -90 |
|
509 else |
|
510 splash^.Angle:= 90; |
|
511 end |
|
512 else |
|
513 splash^.Scale:= abs(hwFloat2Float(Gear^.Density / _3 * Gear^.dY)); |
453 with splash^ do |
514 with splash^ do |
454 begin |
515 begin |
455 Scale:= hwFloat2Float(Gear^.Density / _3 * Gear^.dY); |
516 if Scale > 1 then Scale:= power(Scale,0.3333) |
456 if Scale > 1 then Scale:= power(Scale,0.3333) |
517 else Scale:= Scale + ((1-Scale) / 2); |
457 else Scale:= Scale + ((1-Scale) / 2); |
518 if Scale > 1 then Timer:= round(min(Scale*0.0005/cGravityf,4)) |
458 if Scale > 1 then Timer:= round(min(Scale*0.0005/cGravityf,4)) |
519 else Timer:= 1; |
459 else Timer:= 1; |
520 // Low Gravity |
460 // Low Gravity |
521 FrameTicks:= FrameTicks*Timer; |
461 FrameTicks:= FrameTicks*Timer; |
522 end; |
462 end; |
523 end; |
|
524 |
|
525 // eject water drops |
463 |
526 |
464 maxDrops := (hwRound(Gear^.Density) * 3) div 2 + round(vdX * hwRound(Gear^.Density) * 6) + round(vdY * hwRound(Gear^.Density) * 6); |
527 maxDrops := (hwRound(Gear^.Density) * 3) div 2 + round(vdX * hwRound(Gear^.Density) * 6) + round(vdY * hwRound(Gear^.Density) * 6); |
465 for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do |
528 for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do |
466 begin |
529 begin |
467 particle := AddVisualGear(X - 3 + Random(7), cWaterLine, vgtDroplet); |
530 if isImpactH then |
|
531 begin |
|
532 if isImpactRight then |
|
533 particle := AddVisualGear(RightX, Y - 3 + Random(7), vgtDroplet) |
|
534 else |
|
535 particle := AddVisualGear(LeftX, Y - 3 + Random(7), vgtDroplet) |
|
536 end |
|
537 else |
|
538 particle := AddVisualGear(X - 3 + Random(7), cWaterLine, vgtDroplet); |
|
539 |
468 if particle <> nil then |
540 if particle <> nil then |
469 with particle^ do |
541 with particle^ do |
470 begin |
542 begin |
471 dX := dX - vdX / 10; |
543 // dX and dY were initialized to have a random value on creation (see uVisualGearsList) |
472 dY := dY - vdY / 5; |
544 if isImpactH then |
|
545 begin |
|
546 tmp:= dX; |
|
547 if isImpactRight then |
|
548 dX:= dY - vdX / 5 |
|
549 else |
|
550 dX:= -dy + vdX / 5; |
|
551 dY:= tmp * (1 + vdY / 10); |
|
552 end |
|
553 else |
|
554 begin |
|
555 dX:= dX * (1 + vdX / 10); |
|
556 dY:= dY - vdY / 5; |
|
557 end; |
|
558 |
473 if splash <> nil then |
559 if splash <> nil then |
474 begin |
560 begin |
475 if splash^.Scale > 1 then |
561 if splash^.Scale > 1 then |
476 begin |
562 begin |
477 dX:= dX * power(splash^.Scale,0.3333); // tone down the droplet height further |
563 dX:= dX * power(splash^.Scale,0.3333); // tone down the droplet height further |