hedgewars/GSHandlers.inc
changeset 498 9c8b385dc9a1
parent 495 62c1c2b4414c
child 503 2cfdc4bfc2be
equal deleted inserted replaced
497:adf1aee202c6 498:9c8b385dc9a1
    18 
    18 
    19 procedure doStepDrowningGear(Gear: PGear); forward;
    19 procedure doStepDrowningGear(Gear: PGear); forward;
    20 
    20 
    21 function CheckGearDrowning(Gear: PGear): boolean;
    21 function CheckGearDrowning(Gear: PGear): boolean;
    22 begin
    22 begin
    23 if cWaterLine < Gear^.Y + Gear^.Radius then
    23 if cWaterLine < hwRound(Gear^.Y) + Gear^.Radius then
    24    begin
    24    begin
    25    CheckGearDrowning:= true;
    25    CheckGearDrowning:= true;
    26    Gear^.State:= gstDrowning;
    26    Gear^.State:= gstDrowning;
    27    Gear^.doStep:= @doStepDrowningGear;
    27    Gear^.doStep:= @doStepDrowningGear;
    28    PlaySound(sndSplash, false)
    28    PlaySound(sndSplash, false)
    37    else Gear^.State:= Gear^.State and not gstCollision
    37    else Gear^.State:= Gear^.State and not gstCollision
    38 end;
    38 end;
    39 
    39 
    40 procedure CheckHHDamage(Gear: PGear);
    40 procedure CheckHHDamage(Gear: PGear);
    41 begin
    41 begin
    42 if _0_4 < Gear^.dY then Gear^.Damage:= Gear^.Damage + 1 + hwRound(70 * (hwAbs(Gear^.dY) - _0_4));
    42 if _0_4 < Gear^.dY then Gear^.Damage:= Gear^.Damage + 1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70);
    43 end;
    43 end;
    44 
    44 
    45 ////////////////////////////////////////////////////////////////////////////////
    45 ////////////////////////////////////////////////////////////////////////////////
    46 ////////////////////////////////////////////////////////////////////////////////
    46 ////////////////////////////////////////////////////////////////////////////////
    47 procedure CalcRotationDirAngle(Gear: PGear);
    47 procedure CalcRotationDirAngle(Gear: PGear);
    48 var dAngle: hwFloat;
    48 var dAngle: hwFloat;
    49 begin
    49 begin
    50 dAngle:= (hwAbs(Gear^.dX) + hwAbs(Gear^.dY)) * _0_1;
    50 dAngle:= (hwAbs(Gear^.dX) + hwAbs(Gear^.dY)) * _0_1;
    51 if not Gear^.dX.isNegative then Gear^.DirAngle:= Gear^.DirAngle + dAngle
    51 if not Gear^.dX.isNegative then Gear^.DirAngle:= Gear^.DirAngle + dAngle
    52                 else Gear^.DirAngle:= Gear^.DirAngle - dAngle;
    52                 else Gear^.DirAngle:= Gear^.DirAngle - dAngle;
    53 if Gear^.DirAngle < 0 then Gear^.DirAngle:= Gear^.DirAngle + 16
    53 if Gear^.DirAngle.isNegative then Gear^.DirAngle:= Gear^.DirAngle + _16
    54 else if 16 < Gear^.DirAngle then Gear^.DirAngle:= Gear^.DirAngle - 16
    54 else if _16 < Gear^.DirAngle then Gear^.DirAngle:= Gear^.DirAngle - _16
    55 end;
    55 end;
    56 
    56 
    57 ////////////////////////////////////////////////////////////////////////////////
    57 ////////////////////////////////////////////////////////////////////////////////
    58 procedure doStepDrowningGear(Gear: PGear);
    58 procedure doStepDrowningGear(Gear: PGear);
    59 begin
    59 begin
    85    end else
    85    end else
    86    begin
    86    begin
    87    if hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _1div100000 then
    87    if hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _1div100000 then
    88       if (Gear^.Timer = 0) then Gear^.Active:= false
    88       if (Gear^.Timer = 0) then Gear^.Active:= false
    89                           else begin
    89                           else begin
    90                           Gear^.dX:= 0;
    90                           Gear^.dX:= _0;
    91                           Gear^.dY:= 0
    91                           Gear^.dY:= _0
    92                           end;
    92                           end;
    93    Gear^.State:= Gear^.State or gstCollision
    93    Gear^.State:= Gear^.State or gstCollision
    94    end;
    94    end;
    95 Gear^.X:= Gear^.X + Gear^.dX;
    95 Gear^.X:= Gear^.X + Gear^.dX;
    96 Gear^.Y:= Gear^.Y + Gear^.dY;
    96 Gear^.Y:= Gear^.Y + Gear^.dY;
   101 
   101 
   102 ////////////////////////////////////////////////////////////////////////////////
   102 ////////////////////////////////////////////////////////////////////////////////
   103 procedure doStepCloud(Gear: PGear);
   103 procedure doStepCloud(Gear: PGear);
   104 begin
   104 begin
   105 Gear^.X:= Gear^.X + cWindSpeed * 200 + Gear^.dX;
   105 Gear^.X:= Gear^.X + cWindSpeed * 200 + Gear^.dX;
   106 if Gear^.Y > -160 then Gear^.dY:= Gear^.dY - _1div50000
   106 if hwRound(Gear^.Y) > -160 then Gear^.dY:= Gear^.dY - _1div50000
   107                  else Gear^.dY:= Gear^.dY + _1div50000;
   107                            else Gear^.dY:= Gear^.dY + _1div50000;
   108 Gear^.Y:= Gear^.Y + Gear^.dY;
   108 Gear^.Y:= Gear^.Y + Gear^.dY;
   109 if Gear^.X < -cScreenWidth - 256 then Gear^.X:= cScreenWidth + 2048 else
   109 if hwRound(Gear^.X) < -cScreenWidth - 256 then Gear^.X:= int2hwFloat(cScreenWidth + 2048) else
   110 if Gear^.X > cScreenWidth + 2048 then Gear^.X:= -cScreenWidth - 256
   110 if hwRound(Gear^.X) > cScreenWidth + 2048 then Gear^.X:= int2hwFloat(-cScreenWidth - 256)
   111 end;
   111 end;
   112 
   112 
   113 ////////////////////////////////////////////////////////////////////////////////
   113 ////////////////////////////////////////////////////////////////////////////////
   114 procedure doStepBomb(Gear: PGear);
   114 procedure doStepBomb(Gear: PGear);
   115 var i: LongInt;
   115 var i: LongInt;
   122    case Gear^.Kind of
   122    case Gear^.Kind of
   123         gtAmmo_Bomb: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   123         gtAmmo_Bomb: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   124       gtClusterBomb: begin
   124       gtClusterBomb: begin
   125                      doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
   125                      doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
   126                      for i:= 0 to 4 do
   126                      for i:= 0 to 4 do
   127                          AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, (getrandom - _0_5) * _0_2, (getrandom - 3) * _0_08, 0);
   127                          AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, (getrandom - _0_5) * _0_2, (getrandom - _3) * _0_08, 0);
   128                      end
   128                      end
   129         end;
   129         end;
   130    DeleteGear(Gear);
   130    DeleteGear(Gear);
   131    exit
   131    exit
   132    end;
   132    end;
   143    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, EXPLAutoSound);
   143    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, EXPLAutoSound);
   144    DeleteGear(Gear);
   144    DeleteGear(Gear);
   145    exit
   145    exit
   146    end;
   146    end;
   147 if (GameTicks and $1F) = 0 then
   147 if (GameTicks and $1F) = 0 then
   148    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, 0, 0, 0)
   148    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, _0, _0, 0)
   149 end;
   149 end;
   150 
   150 
   151 ////////////////////////////////////////////////////////////////////////////////
   151 ////////////////////////////////////////////////////////////////////////////////
   152 procedure doStepGrenade(Gear: PGear);
   152 procedure doStepGrenade(Gear: PGear);
   153 begin
   153 begin
   159    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   159    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   160    DeleteGear(Gear);
   160    DeleteGear(Gear);
   161    exit
   161    exit
   162    end;
   162    end;
   163 if (GameTicks and $3F) = 0 then
   163 if (GameTicks and $3F) = 0 then
   164    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, 0, 0, 0)
   164    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, _0, _0, 0)
   165 end;
   165 end;
   166 
   166 
   167 ////////////////////////////////////////////////////////////////////////////////
   167 ////////////////////////////////////////////////////////////////////////////////
   168 procedure doStepHealthTagWork(Gear: PGear);
   168 procedure doStepHealthTagWork(Gear: PGear);
   169 begin
   169 begin
   179 
   179 
   180 procedure doStepHealthTagWorkUnderWater(Gear: PGear);
   180 procedure doStepHealthTagWorkUnderWater(Gear: PGear);
   181 begin
   181 begin
   182 AllInactive:= false;
   182 AllInactive:= false;
   183 Gear^.Y:= Gear^.Y - _0_08;
   183 Gear^.Y:= Gear^.Y - _0_08;
   184 if Gear^.Y < cWaterLine + 10 then
   184 if hwRound(Gear^.Y) < cWaterLine + 10 then
   185    DeleteGear(Gear)
   185    DeleteGear(Gear)
   186 end;
   186 end;
   187 
   187 
   188 procedure doStepHealthTag(Gear: PGear);
   188 procedure doStepHealthTag(Gear: PGear);
   189 var s: shortstring;
   189 var s: shortstring;
   190 begin
   190 begin
   191 AllInactive:= false;
   191 AllInactive:= false;
   192 str(Gear^.State, s);
   192 str(Gear^.State, s);
   193 Gear^.Surf:= RenderString(s, PHedgehog(Gear^.Hedgehog)^.Team^.Color, fnt16);
   193 Gear^.Surf:= RenderString(s, PHedgehog(Gear^.Hedgehog)^.Team^.Color, fnt16);
   194 if Gear^.Y < cWaterLine then Gear^.doStep:= @doStepHealthTagWork
   194 if hwRound(Gear^.Y) < cWaterLine then Gear^.doStep:= @doStepHealthTagWork
   195                        else Gear^.doStep:= @doStepHealthTagWorkUnderWater
   195                                  else Gear^.doStep:= @doStepHealthTagWorkUnderWater
   196 end;
   196 end;
   197 
   197 
   198 ////////////////////////////////////////////////////////////////////////////////
   198 ////////////////////////////////////////////////////////////////////////////////
   199 procedure doStepGrave(Gear: PGear);
   199 procedure doStepGrave(Gear: PGear);
   200 begin
   200 begin
   201 AllInactive:= false;
   201 AllInactive:= false;
   202 if Gear^.dY < 0 then
   202 if Gear^.dY.isNegative then
   203    if TestCollisionY(Gear, -1) then Gear^.dY:= 0;
   203    if TestCollisionY(Gear, -1) then Gear^.dY:= _0;
   204 
   204 
   205 if not Gear^.dY.isNegative then
   205 if not Gear^.dY.isNegative then
   206    if TestCollisionY(Gear, 1) then
   206    if TestCollisionY(Gear, 1) then
   207       begin
   207       begin
   208       Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
   208       Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
   234 
   234 
   235 if (GameTicks and $3F) = 0 then
   235 if (GameTicks and $3F) = 0 then
   236    begin
   236    begin
   237    y:= hwRound(Gear^.Y);
   237    y:= hwRound(Gear^.Y);
   238    if y + Gear^.Radius < cWaterLine then
   238    if y + Gear^.Radius < cWaterLine then
   239       AddGear(hwRound(Gear^.X), y, gtSmokeTrace, 0, 0, 0, 0);
   239       AddGear(hwRound(Gear^.X), y, gtSmokeTrace, 0, _0, _0, 0);
   240    end;
   240    end;
   241 
   241 
   242 CheckCollision(Gear);
   242 CheckCollision(Gear);
   243 dec(Gear^.Timer);
   243 dec(Gear^.Timer);
   244 if ((Gear^.State and gstCollision) <> 0) or (Gear^.Timer = 0) then
   244 if ((Gear^.State and gstCollision) <> 0) or (Gear^.Timer = 0) then
   293    AfterAttack;
   293    AfterAttack;
   294    exit
   294    exit
   295    end;
   295    end;
   296 dec(i)
   296 dec(i)
   297 until i = 0;
   297 until i = 0;
   298 if (Gear^.X < 0) or (Gear^.Y < 0) or (Gear^.X > 2048) or (Gear^.Y > 1024) then
   298 if (Gear^.X < _0) or (Gear^.Y < _0) or (Gear^.X > _2048) or (Gear^.Y > _1024) then
   299    begin
   299    begin
   300    DeleteGear(Gear);
   300    DeleteGear(Gear);
   301    AfterAttack
   301    AfterAttack
   302    end
   302    end
   303 end;
   303 end;
   325    begin
   325    begin
   326    DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
   326    DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
   327    dec(Gear^.Health, Gear^.Damage);
   327    dec(Gear^.Health, Gear^.Damage);
   328    Gear^.Damage:= 0
   328    Gear^.Damage:= 0
   329    end;
   329    end;
   330 if (Gear^.Health <= 0) or (Gear^.X < 0) or (Gear^.Y < 0) or (Gear^.X > 2048) or (Gear^.Y > 1024) then
   330 if (Gear^.Health <= 0) or (Gear^.X < _0) or (Gear^.Y < _0) or (Gear^.X > _2048) or (Gear^.Y > _1024) then
   331    DeleteGear(Gear)
   331    DeleteGear(Gear)
   332 end;
   332 end;
   333 
   333 
   334 ////////////////////////////////////////////////////////////////////////////////
   334 ////////////////////////////////////////////////////////////////////////////////
   335 procedure doStepActionTimer(Gear: PGear);
   335 procedure doStepActionTimer(Gear: PGear);
   394    Gear^.Y:= Gear^.Y + _1_9;
   394    Gear^.Y:= Gear^.Y + _1_9;
   395    SetAllHHToActive;
   395    SetAllHHToActive;
   396    end;
   396    end;
   397 if TestCollisionYwithGear(Gear, 1) then
   397 if TestCollisionYwithGear(Gear, 1) then
   398    begin
   398    begin
   399    Gear^.dY:= 0;
   399    Gear^.dY:= _0;
   400    SetLittle(HHGear^.dX);
   400    SetLittle(HHGear^.dX);
   401    HHGear^.dY:= 0;
   401    HHGear^.dY:= _0;
   402    end else
   402    end else
   403    begin
   403    begin
   404    Gear^.dY:= Gear^.dY + cGravity;
   404    Gear^.dY:= Gear^.dY + cGravity;
   405    Gear^.Y:= Gear^.Y + Gear^.dY;
   405    Gear^.Y:= Gear^.Y + Gear^.dY;
   406    if Gear^.Y > 1024 then Gear^.Timer:= 1
   406    if Gear^.Y > _1024 then Gear^.Timer:= 1
   407    end;
   407    end;
   408 
   408 
   409 Gear^.X:= Gear^.X + HHGear^.dX;
   409 Gear^.X:= Gear^.X + HHGear^.dX;
   410 HHGear^.X:= Gear^.X;
   410 HHGear^.X:= Gear^.X;
   411 HHGear^.Y:= Gear^.Y - cHHRadius;
   411 HHGear^.Y:= Gear^.Y - int2hwFloat(cHHRadius);
   412 
   412 
   413 if (Gear^.Message and gm_Attack) <> 0 then
   413 if (Gear^.Message and gm_Attack) <> 0 then
   414    if (Gear^.State and gsttmpFlag) <> 0 then Gear^.Timer:= 1 else else
   414    if (Gear^.State and gsttmpFlag) <> 0 then Gear^.Timer:= 1 else else
   415    if (Gear^.State and gsttmpFlag) = 0 then Gear^.State:= Gear^.State or gsttmpFlag;
   415    if (Gear^.State and gsttmpFlag) = 0 then Gear^.State:= Gear^.State or gsttmpFlag;
   416 if ((Gear^.Message and gm_Left) <> 0) then Gear^.dX:= - _0_3 else
   416 if ((Gear^.Message and gm_Left) <> 0) then Gear^.dX:= - _0_3 else
   417    if ((Gear^.Message and gm_Right) <> 0) then Gear^.dX:= _0_3
   417    if ((Gear^.Message and gm_Right) <> 0) then Gear^.dX:= _0_3
   418                                          else Gear^.dX:= 0;
   418                                           else Gear^.dX:= _0;
   419 end;
   419 end;
   420 
   420 
   421 procedure doStepPickHammer(Gear: PGear);
   421 procedure doStepPickHammer(Gear: PGear);
   422 var i, y: LongInt;
   422 var i, y: LongInt;
   423     ar: TRangeArray;
   423     ar: TRangeArray;
   424 begin
   424 begin
   425 i:= 0;
   425 i:= 0;
   426 y:= hwRound(Gear^.Y) - cHHRadius*2;
   426 y:= hwRound(Gear^.Y) - cHHRadius * 2;
   427 while y < hwRound(Gear^.Y) do
   427 while y < hwRound(Gear^.Y) do
   428    begin
   428    begin
   429    ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
   429    ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
   430    ar[i].Right:= hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
   430    ar[i].Right:= hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
   431    inc(y, 2);
   431    inc(y, 2);
   432    inc(i)
   432    inc(i)
   433    end;
   433    end;
   434 DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius*2, 2, Pred(i));
   434 DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius * 2, 2, Pred(i));
   435 Gear^.dY:= PHedgehog(Gear^.Hedgehog)^.Gear^.dY;
   435 Gear^.dY:= PHedgehog(Gear^.Hedgehog)^.Gear^.dY;
   436 PlaySound(sndPickhammer, true);
   436 PlaySound(sndPickhammer, true);
   437 doStepPickHammerWork(Gear);
   437 doStepPickHammerWork(Gear);
   438 Gear^.doStep:= @doStepPickHammerWork
   438 Gear^.doStep:= @doStepPickHammerWork
   439 end;
   439 end;
   453 
   453 
   454 b:= false;
   454 b:= false;
   455 
   455 
   456 if abs(LongInt(HHGear^.Angle) - BTPrevAngle) > 7  then
   456 if abs(LongInt(HHGear^.Angle) - BTPrevAngle) > 7  then
   457    begin
   457    begin
   458    Gear^.dX:= hwSign(HHGear^.dX) * AngleSin(HHGear^.Angle) * _0_5;
   458    Gear^.dX:= SignAs(AngleSin(HHGear^.Angle) * _0_5, HHGear^.dX);
   459    Gear^.dY:= AngleCos(HHGear^.Angle) * ( - _0_5);
   459    Gear^.dY:= AngleCos(HHGear^.Angle) * ( - _0_5);
   460    BTPrevAngle:= HHGear^.Angle;
   460    BTPrevAngle:= HHGear^.Angle;
   461    b:= true
   461    b:= true
   462    end;
   462    end;
   463 
   463 
   464 if Gear^.Timer mod cHHStepTicks = 0 then
   464 if Gear^.Timer mod cHHStepTicks = 0 then
   465    begin
   465    begin
   466    b:= true;
   466    b:= true;
   467    if Gear^.dX < 0 then HHGear^.Message:= (HHGear^.Message or gm_Left) and not gm_Right
   467    if Gear^.dX.isNegative then HHGear^.Message:= (HHGear^.Message or gm_Left) and not gm_Right
   468                   else HHGear^.Message:= (HHGear^.Message or gm_Right) and not gm_Left;
   468                           else HHGear^.Message:= (HHGear^.Message or gm_Right) and not gm_Left;
   469 
   469 
   470    HHGear^.State:= HHGear^.State and not gstAttacking;
   470    HHGear^.State:= HHGear^.State and not gstAttacking;
   471    HedgehogStep(HHGear);
   471    HedgehogStep(HHGear);
   472    HHGear^.State:= HHGear^.State or gstAttacking;
   472    HHGear^.State:= HHGear^.State or gstAttacking;
   473 
   473 
   484 
   484 
   485    if (HHGear^.State and gstFalling) <> 0 then Gear^.Timer:= 0
   485    if (HHGear^.State and gstFalling) <> 0 then Gear^.Timer:= 0
   486    end;
   486    end;
   487 
   487 
   488 if b then
   488 if b then
   489    DrawTunnel(HHGear^.X - Gear^.dX * cHHRadius, HHGear^.Y - 4 - Gear^.dY * cHHRadius + hwAbs(Gear^.dY) * 7,
   489    DrawTunnel(HHGear^.X - Gear^.dX * cHHRadius, HHGear^.Y - _4 - Gear^.dY * cHHRadius + hwAbs(Gear^.dY) * 7,
   490               Gear^.dX, Gear^.dY,
   490               Gear^.dX, Gear^.dY,
   491               cHHRadius * 5, cHHRadius * 2 + 6);
   491               cHHRadius * 5, cHHRadius * 2 + 6);
   492 
   492 
   493 if (Gear^.Timer = 0) or ((HHGear^.Message and gm_Attack) <> 0) then
   493 if (Gear^.Timer = 0) or ((HHGear^.Message and gm_Attack) <> 0) then
   494    begin
   494    begin
   545 
   545 
   546 if not TestCollisionYwithGear(HHGear, 1) then HHGear^.dY:= HHGear^.dY + cGravity;
   546 if not TestCollisionYwithGear(HHGear, 1) then HHGear^.dY:= HHGear^.dY + cGravity;
   547 
   547 
   548 cs:= Gear^.dY + HHGear^.dY;
   548 cs:= Gear^.dY + HHGear^.dY;
   549 cc:= Gear^.dX + HHGear^.dX;
   549 cc:= Gear^.dX + HHGear^.dX;
   550 len:= 1 / Distance(cc, cs);
   550 len:= _1 / Distance(cc, cs);
   551 cc:= cc * len;
   551 cc:= cc * len;
   552 cs:= cs * len;
   552 cs:= cs * len;
   553 
   553 
   554 flCheck:= not flCheck;
   554 flCheck:= not flCheck;
   555 if flCheck then  // check whether rope needs dividing
   555 if flCheck then  // check whether rope needs dividing
   556    begin
   556    begin
   557    len:= Gear^.Elasticity - 20;
   557    len:= Gear^.Elasticity - _20;
   558    while len > 5 do
   558    while len > _5 do
   559          begin
   559          begin
   560          tx:= cc*len;
   560          tx:= cc*len;
   561          ty:= cs*len;
   561          ty:= cs*len;
   562          lx:= hwRound(Gear^.X + tx) + hwSign(HHGear^.dX);
   562          lx:= hwRound(Gear^.X + tx) + hwSign(HHGear^.dX);
   563          ly:= hwRound(Gear^.Y + ty) + hwSign(HHGear^.dY);
   563          ly:= hwRound(Gear^.Y + ty) + hwSign(HHGear^.dY);
   576            inc(RopePoints.Count);
   576            inc(RopePoints.Count);
   577            Gear^.Elasticity:= Gear^.Elasticity - len;
   577            Gear^.Elasticity:= Gear^.Elasticity - len;
   578            Gear^.Friction:= Gear^.Friction - len;
   578            Gear^.Friction:= Gear^.Friction - len;
   579            break
   579            break
   580            end;
   580            end;
   581          len:= len - 3
   581          len:= len - _3
   582          end;
   582          end;
   583    end else
   583    end else
   584    if RopePoints.Count > 0 then // check whether the last dividing point could be removed
   584    if RopePoints.Count > 0 then // check whether the last dividing point could be removed
   585       begin
   585       begin
   586       tx:= RopePoints.ar[Pred(RopePoints.Count)].X;
   586       tx:= RopePoints.ar[Pred(RopePoints.Count)].X;
   598 Gear^.dX:= HHGear^.X - Gear^.X;
   598 Gear^.dX:= HHGear^.X - Gear^.X;
   599 Gear^.dY:= HHGear^.Y - Gear^.Y;
   599 Gear^.dY:= HHGear^.Y - Gear^.Y;
   600 
   600 
   601 cs:= Gear^.dY + HHGear^.dY;
   601 cs:= Gear^.dY + HHGear^.dY;
   602 cc:= Gear^.dX + HHGear^.dX;
   602 cc:= Gear^.dX + HHGear^.dX;
   603 len:= 1 / Distance(cc, cs);
   603 len:= _1 / Distance(cc, cs);
   604 cc:= cc * len;
   604 cc:= cc * len;
   605 cs:= cs * len;
   605 cs:= cs * len;
   606 
   606 
   607 HHGear^.dX:= HHGear^.X;
   607 HHGear^.dX:= HHGear^.X;
   608 HHGear^.dY:= HHGear^.Y;
   608 HHGear^.dY:= HHGear^.Y;
   609 
   609 
   610 if ((Gear^.Message and gm_Down) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
   610 if ((Gear^.Message and gm_Down) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
   611    if not (TestCollisionXwithGear(HHGear, hwSign(Gear^.dX))
   611    if not (TestCollisionXwithGear(HHGear, hwSign(Gear^.dX))
   612         or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY))) then Gear^.Elasticity:= Gear^.Elasticity + _0_3;
   612         or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY))) then Gear^.Elasticity:= Gear^.Elasticity + _0_3;
   613 
   613 
   614 if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Elasticity > 30) then
   614 if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Elasticity > _30) then
   615    if not (TestCollisionXwithGear(HHGear, -hwSign(Gear^.dX))
   615    if not (TestCollisionXwithGear(HHGear, -hwSign(Gear^.dX))
   616         or TestCollisionYwithGear(HHGear, -hwSign(Gear^.dY))) then Gear^.Elasticity:= Gear^.Elasticity - _0_3;
   616         or TestCollisionYwithGear(HHGear, -hwSign(Gear^.dY))) then Gear^.Elasticity:= Gear^.Elasticity - _0_3;
   617 
   617 
   618 HHGear^.X:= Gear^.X + cc*Gear^.Elasticity;
   618 HHGear^.X:= Gear^.X + cc*Gear^.Elasticity;
   619 HHGear^.Y:= Gear^.Y + cs*Gear^.Elasticity;
   619 HHGear^.Y:= Gear^.Y + cs*Gear^.Elasticity;
   636 var HHGear: PGear;
   636 var HHGear: PGear;
   637     tx, ty, tt: hwFloat;
   637     tx, ty, tt: hwFloat;
   638 begin
   638 begin
   639 Gear^.X:= Gear^.X - Gear^.dX;
   639 Gear^.X:= Gear^.X - Gear^.dX;
   640 Gear^.Y:= Gear^.Y - Gear^.dY;
   640 Gear^.Y:= Gear^.Y - Gear^.dY;
   641 Gear^.Elasticity:= Gear^.Elasticity + 1;
   641 Gear^.Elasticity:= Gear^.Elasticity + _1;
   642 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   642 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   643 if (HHGear^.State and gstFalling) <> 0 then
   643 if (HHGear^.State and gstFalling) <> 0 then
   644    if TestCollisionYwithGear(HHGear, 1) then
   644    if TestCollisionYwithGear(HHGear, 1) then
   645       begin
   645       begin
   646       HHGear^.dY:= 0;
   646       HHGear^.dY:= _0;
   647       CheckHHDamage(HHGear);
   647       CheckHHDamage(HHGear);
   648       HHGear^.State:= HHGear^.State and not (gstFalling or gstHHJumping);
   648       HHGear^.State:= HHGear^.State and not (gstFalling or gstHHJumping);
   649       end else
   649       end else
   650       begin
   650       begin
   651       if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
   651       if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
   653       HHGear^.Y:= HHGear^.Y + HHGear^.dY;
   653       HHGear^.Y:= HHGear^.Y + HHGear^.dY;
   654       Gear^.X:= Gear^.X + HHGear^.dX;
   654       Gear^.X:= Gear^.X + HHGear^.dX;
   655       Gear^.Y:= Gear^.Y + HHGear^.dY;
   655       Gear^.Y:= Gear^.Y + HHGear^.dY;
   656       HHGear^.dY:= HHGear^.dY + cGravity;
   656       HHGear^.dY:= HHGear^.dY + cGravity;
   657       tt:= Gear^.Elasticity;
   657       tt:= Gear^.Elasticity;
   658       tx:= 0;
   658       tx:= _0;
   659       ty:= 0;
   659       ty:= _0;
   660       while tt > 20 do
   660       while tt > _20 do
   661             begin
   661             begin
   662             if  TestCollisionXwithXYShift(Gear, hwRound(tx), hwRound(ty), hwSign(Gear^.dX))
   662             if  TestCollisionXwithXYShift(Gear, tx, hwRound(ty), hwSign(Gear^.dX))
   663              or TestCollisionYwithXYShift(Gear, hwRound(tx), hwRound(ty), hwSign(Gear^.dY)) then
   663              or TestCollisionYwithXYShift(Gear, hwRound(tx), hwRound(ty), hwSign(Gear^.dY)) then
   664                 begin
   664                 begin
   665                 Gear^.X:= Gear^.X + tx;
   665                 Gear^.X:= Gear^.X + tx;
   666                 Gear^.Y:= Gear^.Y + ty;
   666                 Gear^.Y:= Gear^.Y + ty;
   667                 Gear^.Elasticity:= tt;
   667                 Gear^.Elasticity:= tt;
   668                 Gear^.doStep:= @doStepRopeWork;
   668                 Gear^.doStep:= @doStepRopeWork;
   669                 with HHGear^ do State:= State and not gstAttacking;
   669                 with HHGear^ do State:= State and not gstAttacking;
   670                 tt:= 0
   670                 tt:= _0
   671                 end;
   671                 end;
   672             tx:= tx + Gear^.dX - Gear^.dX;
   672             tx:= tx + Gear^.dX - Gear^.dX;
   673             ty:= ty + Gear^.dY - Gear^.dY;
   673             ty:= ty + Gear^.dY - Gear^.dY;
   674             tt:= tt - 2;
   674             tt:= tt - _2;
   675             end;
   675             end;
   676       end;
   676       end;
   677 CheckCollision(Gear);
   677 CheckCollision(Gear);
   678 if (Gear^.State and gstCollision) <> 0 then
   678 if (Gear^.State and gstCollision) <> 0 then
   679    begin
   679    begin
   680    Gear^.doStep:= @doStepRopeWork;
   680    Gear^.doStep:= @doStepRopeWork;
   681    with HHGear^ do State:= State and not gstAttacking;
   681    with HHGear^ do State:= State and not gstAttacking;
   682    if Gear^.Elasticity < 10 then
   682    if Gear^.Elasticity < _10 then
   683       Gear^.Elasticity:= 10000;
   683       Gear^.Elasticity:= _10000;
   684    end;
   684    end;
   685 
   685 
   686 if (Gear^.Elasticity > Gear^.Friction) or ((Gear^.Message and gm_Attack) = 0) then
   686 if (Gear^.Elasticity > Gear^.Friction) or ((Gear^.Message and gm_Attack) = 0) then
   687    begin
   687    begin
   688    with PHedgehog(Gear^.Hedgehog)^.Gear^ do
   688    with PHedgehog(Gear^.Hedgehog)^.Gear^ do
   735    if Gear^.CollIndex < High(Longword) then DeleteCI(Gear);
   735    if Gear^.CollIndex < High(Longword) then DeleteCI(Gear);
   736    doStepFallingGear(Gear);
   736    doStepFallingGear(Gear);
   737    if Gear^.Active = false then
   737    if Gear^.Active = false then
   738       begin
   738       begin
   739       if Gear^.CollIndex = High(Longword) then AddGearCI(Gear);
   739       if Gear^.CollIndex = High(Longword) then AddGearCI(Gear);
   740       Gear^.dX:= 0;
   740       Gear^.dX:= _0;
   741       Gear^.dY:= 0
   741       Gear^.dY:= _0
   742       end;
   742       end;
   743    CalcRotationDirAngle(Gear);
   743    CalcRotationDirAngle(Gear);
   744    AllInactive:= false
   744    AllInactive:= false
   745    end;
   745    end;
   746 
   746 
   796    x:= hwRound(Gear^.X);
   796    x:= hwRound(Gear^.X);
   797    y:= hwRound(Gear^.Y);
   797    y:= hwRound(Gear^.Y);
   798    DeleteGear(Gear);
   798    DeleteGear(Gear);
   799    doMakeExplosion(x, y, 25, EXPLAutoSound);
   799    doMakeExplosion(x, y, 25, EXPLAutoSound);
   800    for i:= 0 to 63 do
   800    for i:= 0 to 63 do
   801        AddGear(x, y, gtFlame, 0, 0, 0, 0);
   801        AddGear(x, y, gtFlame, 0, _0, _0, 0);
   802    exit
   802    exit
   803    end;
   803    end;
   804 
   804 
   805 if (Gear^.dY.QWordValue <> 0) or (not TestCollisionYwithGear(Gear, 1)) then
   805 if (Gear^.dY.QWordValue <> 0) or (not TestCollisionYwithGear(Gear, 1)) then
   806    begin
   806    begin
   807    AllInactive:= false;
   807    AllInactive:= false;
   808    Gear^.dY:= Gear^.dY + cGravity;
   808    Gear^.dY:= Gear^.dY + cGravity;
   809    Gear^.Y:= Gear^.Y + Gear^.dY;
   809    Gear^.Y:= Gear^.Y + Gear^.dY;
   810    if (Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= 0 else
   810    if (Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= _0 else
   811    if (not Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, 1) then
   811    if (not Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, 1) then
   812       begin
   812       begin
   813       Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
   813       Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
   814       if Gear^.dY > - _0_001 then Gear^.dY:= 0
   814       if Gear^.dY > - _0_001 then Gear^.dY:= _0
   815          else if Gear^.dY < - _0_03 then PlaySound(sndGraveImpact, false);
   815          else if Gear^.dY < - _0_03 then PlaySound(sndGraveImpact, false);
   816       end;
   816       end;
   817    CheckGearDrowning(Gear);
   817    CheckGearDrowning(Gear);
   818    end;
   818    end;
   819 
   819 
   903    Gear^.dY:= Gear^.dY + cGravity;
   903    Gear^.dY:= Gear^.dY + cGravity;
   904    if hwAbs(Gear^.dX) > _0_1 then Gear^.dX:= Gear^.dX * _0_5;
   904    if hwAbs(Gear^.dX) > _0_1 then Gear^.dX:= Gear^.dX * _0_5;
   905    if Gear^.dY > _0_1 then Gear^.dY:= Gear^.dY * _0_995;
   905    if Gear^.dY > _0_1 then Gear^.dY:= Gear^.dY * _0_995;
   906    Gear^.X:= Gear^.X + Gear^.dX;
   906    Gear^.X:= Gear^.X + Gear^.dX;
   907    Gear^.Y:= Gear^.Y + Gear^.dY;
   907    Gear^.Y:= Gear^.Y + Gear^.dY;
   908    if Gear^.Y > 1023 then
   908    if not (Gear^.Y < _1024) then
   909       begin
   909       begin
   910       DeleteGear(Gear);
   910       DeleteGear(Gear);
   911       exit
   911       exit
   912       end
   912       end
   913    end else begin
   913    end else begin
   940 
   940 
   941 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   941 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   942 if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then
   942 if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then
   943    begin
   943    begin
   944    Gear^.Tag:= hwRound(HHGear^.Y);
   944    Gear^.Tag:= hwRound(HHGear^.Y);
   945    DrawTunnel(HHGear^.X - cHHRadius, HHGear^.Y - 1, _0_5, 0, cHHRadius * 4, 2);
   945    DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4, 2);
   946    HHGear^.State:= HHGear^.State or gstNoDamage;
   946    HHGear^.State:= HHGear^.State or gstNoDamage;
   947    Gear^.Y:= HHGear^.Y;
   947    Gear^.Y:= HHGear^.Y;
   948    AmmoShove(Gear, 30, 40);
   948    AmmoShove(Gear, 30, 40);
   949    HHGear^.State:= HHGear^.State and not gstNoDamage
   949    HHGear^.State:= HHGear^.State and not gstNoDamage
   950    end;
   950    end;
   963 procedure doStepFirePunch(Gear: PGear);
   963 procedure doStepFirePunch(Gear: PGear);
   964 var HHGear: PGear;
   964 var HHGear: PGear;
   965 begin
   965 begin
   966 AllInactive:= false;
   966 AllInactive:= false;
   967 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   967 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   968 HHGear^.X:= hwRound(HHGear^.X) - _0_5;
   968 HHGear^.X:= int2hwFloat(hwRound(HHGear^.X)) - _0_5;
   969 SetLittle(HHGear^.dX);
   969 SetLittle(HHGear^.dX);
   970 HHGear^.dY:= - _0_3;
   970 HHGear^.dY:= - _0_3;
   971 
   971 
   972 Gear^.X:= HHGear^.X;
   972 Gear^.X:= HHGear^.X;
   973 Gear^.dX:= hwSign(HHGear^.dX) * _0_45;
   973 Gear^.dX:= SignAs(_0_45, HHGear^.dX);
   974 Gear^.dY:= - _0_9;
   974 Gear^.dY:= - _0_9;
   975 Gear^.doStep:= @doStepFirePunchWork;
   975 Gear^.doStep:= @doStepFirePunchWork;
   976 DrawTunnel(HHGear^.X - cHHRadius, HHGear^.Y + 1, _0_5, 0, cHHRadius * 4, 5);
   976 DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y + _1, _0_5, _0, cHHRadius * 4, 5);
   977 end;
   977 end;
   978 
   978 
   979 ////////////////////////////////////////////////////////////////////////////////
   979 ////////////////////////////////////////////////////////////////////////////////
   980 
   980 
   981 procedure doStepParachute(Gear: PGear);
   981 procedure doStepParachute(Gear: PGear);
   990    begin
   990    begin
   991    with HHGear^ do
   991    with HHGear^ do
   992         begin
   992         begin
   993         Message:= 0;
   993         Message:= 0;
   994         SetLittle(dx);
   994         SetLittle(dx);
   995         dY:= 0;
   995         dY:= _0;
   996         State:= State and not (gstAttacking or gstAttacked);
   996         State:= State and not (gstAttacking or gstAttacked);
   997         State:= State or gstFalling;
   997         State:= State or gstFalling;
   998         end;
   998         end;
   999    DeleteGear(Gear);
   999    DeleteGear(Gear);
  1000    OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^.Ammo);
  1000    OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^.Ammo);
  1019       cBombsSpeed   : hwFloat = (isNegative: false; QWordValue:  429496729);
  1019       cBombsSpeed   : hwFloat = (isNegative: false; QWordValue:  429496729);
  1020 
  1020 
  1021 procedure doStepAirAttackWork(Gear: PGear);
  1021 procedure doStepAirAttackWork(Gear: PGear);
  1022 begin
  1022 begin
  1023 AllInactive:= false;
  1023 AllInactive:= false;
  1024 Gear^.X:= Gear^.X + Gear^.Tag * cAirPlaneSpeed;
  1024 Gear^.X:= Gear^.X + cAirPlaneSpeed * Gear^.Tag;
  1025 if (Gear^.Health > 0)and( not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  1025 if (Gear^.Health > 0)and( not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  1026    begin
  1026    begin
  1027    dec(Gear^.Health);
  1027    dec(Gear^.Health);
  1028    case Gear^.State of
  1028    case Gear^.State of
  1029         0: FollowGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.Tag * cBombsSpeed, 0, 0);
  1029         0: FollowGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  1030         1: FollowGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, Gear^.Tag * cBombsSpeed, 0, 0);
  1030         1: FollowGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed * Gear^.Tag, _0, 0);
  1031         end;
  1031         end;
  1032    Gear^.dX:= Gear^.dX + Gear^.Tag * cBombsDistance
  1032    Gear^.dX:= Gear^.dX + cBombsDistance * Gear^.Tag
  1033    end;
  1033    end;
  1034 if (Gear^.X > 3072) or (Gear^.X < -1024) then DeleteGear(Gear)
  1034 if (hwRound(Gear^.X) > 3072) or (hwRound(Gear^.X) < -1024) then DeleteGear(Gear)
  1035 end;
  1035 end;
  1036 
  1036 
  1037 procedure doStepAirAttack(Gear: PGear);
  1037 procedure doStepAirAttack(Gear: PGear);
  1038 begin
  1038 begin
  1039 AllInactive:= false;
  1039 AllInactive:= false;
  1040 if Gear^.X.QWordValue = 0 then Gear^.Tag:=  1
  1040 if Gear^.X.QWordValue = 0 then Gear^.Tag:=  1
  1041                           else Gear^.Tag:= -1;
  1041                           else Gear^.Tag:= -1;
  1042 Gear^.X:= 1024 - Gear^.Tag * 2048;
  1042 Gear^.X:= _1024 - _2048 * Gear^.Tag;
  1043 Gear^.Y:= -128;
  1043 Gear^.Y:= -_128;
  1044 Gear^.dX:= TargetPoint.X -
  1044 Gear^.dX:= int2hwFloat(TargetPoint.X) -
  1045            Gear^.Tag * cBombsDistance * 5 / 2;
  1045            cBombsDistance * _5 * Gear^.Tag / _2;
  1046 
  1046 
  1047 if TargetPoint.Y - Gear^.Y > 0 then
  1047 if TargetPoint.Y - hwRound(Gear^.Y) > 0 then
  1048    Gear^.dX:= Gear^.dX - Gear^.Tag * cBombsSpeed * hwSqrt(2 * (TargetPoint.Y - Gear^.Y) / cGravity);
  1048    Gear^.dX:= Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(TargetPoint.Y) - Gear^.Y) * 2 / cGravity) * Gear^.Tag;
  1049 Gear^.Health:= 6;
  1049 Gear^.Health:= 6;
  1050 Gear^.doStep:= @doStepAirAttackWork
  1050 Gear^.doStep:= @doStepAirAttackWork
  1051 end;
  1051 end;
  1052 
  1052 
  1053 ////////////////////////////////////////////////////////////////////////////////
  1053 ////////////////////////////////////////////////////////////////////////////////
  1061    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
  1061    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
  1062    DeleteGear(Gear);
  1062    DeleteGear(Gear);
  1063    exit
  1063    exit
  1064    end;
  1064    end;
  1065 if (GameTicks and $3F) = 0 then
  1065 if (GameTicks and $3F) = 0 then
  1066    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, 0, 0, 0)
  1066    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, _0, _0, 0)
  1067 end;
  1067 end;
  1068 
  1068 
  1069 ////////////////////////////////////////////////////////////////////////////////
  1069 ////////////////////////////////////////////////////////////////////////////////
  1070 
  1070 
  1071 procedure doStepGirder(Gear: PGear);
  1071 procedure doStepGirder(Gear: PGear);