hedgewars/GSHandlers.inc
changeset 351 29bc9c36ad5f
parent 346 fc1e0a4f152c
child 355 40c68869899e
equal deleted inserted replaced
350:c3ccec3834e8 351:29bc9c36ad5f
    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 Result:= Gear.Y + Gear.Radius >= cWaterLine;
    23 if cWaterLine < Gear^.Y + Gear^.Radius then
    24 if Result then
    24    begin
    25    begin
    25    CheckGearDrowning:= true;
    26    Gear.State:= gstDrowning;
    26    Gear^.State:= gstDrowning;
    27    Gear.doStep:= doStepDrowningGear;
    27    Gear^.doStep:= @doStepDrowningGear;
    28    PlaySound(sndSplash)
    28    PlaySound(sndSplash, false)
    29    end
    29    end else
       
    30    CheckGearDrowning:= false
    30 end;
    31 end;
    31 
    32 
    32 procedure CheckCollision(Gear: PGear);
    33 procedure CheckCollision(Gear: PGear);
    33 begin
    34 begin
    34 if TestCollisionXwithGear(Gear, hwSign(Gear.X)) or TestCollisionYwithGear(Gear, hwSign(Gear.Y))
    35 if TestCollisionXwithGear(Gear, hwSign(Gear^.X)) or TestCollisionYwithGear(Gear, hwSign(Gear^.Y))
    35    then Gear.State:= Gear.State or      gstCollision
    36    then Gear^.State:= Gear^.State or      gstCollision
    36    else Gear.State:= Gear.State and not gstCollision
    37    else Gear^.State:= Gear^.State and not gstCollision
    37 end;
    38 end;
    38 
    39 
    39 procedure CheckHHDamage(Gear: PGear);
    40 procedure CheckHHDamage(Gear: PGear);
    40 begin
    41 begin
    41 if Gear.dY > 0.40 then Gear.Damage:= Gear.Damage + 1 + round(70 * (abs(Gear.dY) - 0.40));
    42 if _0_4 < Gear^.dY then Gear^.Damage:= Gear^.Damage + 1 + hwRound(70 * (hwAbs(Gear^.dY) - _0_4));
    42 end;
    43 end;
    43 
    44 
    44 ////////////////////////////////////////////////////////////////////////////////
    45 ////////////////////////////////////////////////////////////////////////////////
    45 ////////////////////////////////////////////////////////////////////////////////
    46 ////////////////////////////////////////////////////////////////////////////////
    46 procedure CalcRotationDirAngle(Gear: PGear);
    47 procedure CalcRotationDirAngle(Gear: PGear);
    47 var dAngle: Double;
    48 var dAngle: hwFloat;
    48 begin
    49 begin
    49 dAngle:= (abs(Gear.dX) + abs(Gear.dY))*0.1;
    50 dAngle:= (hwAbs(Gear^.dX) + hwAbs(Gear^.dY)) * _0_1;
    50 if Gear.dX >= 0 then Gear.DirAngle:= Gear.DirAngle + dAngle
    51 if not Gear^.dX.isNegative then Gear^.DirAngle:= Gear^.DirAngle + dAngle
    51                 else Gear.DirAngle:= Gear.DirAngle - dAngle;
    52                 else Gear^.DirAngle:= Gear^.DirAngle - dAngle;
    52 if Gear.DirAngle < 0 then Gear.DirAngle:= Gear.DirAngle + 16
    53 if Gear^.DirAngle < 0 then Gear^.DirAngle:= Gear^.DirAngle + 16
    53 else if Gear.DirAngle >= 16 then Gear.DirAngle:= Gear.DirAngle - 16
    54 else if 16 < Gear^.DirAngle then Gear^.DirAngle:= Gear^.DirAngle - 16
    54 end;
    55 end;
    55 
    56 
    56 ////////////////////////////////////////////////////////////////////////////////
    57 ////////////////////////////////////////////////////////////////////////////////
    57 procedure doStepDrowningGear(Gear: PGear);
    58 procedure doStepDrowningGear(Gear: PGear);
    58 begin
    59 begin
    59 AllInactive:= false;
    60 AllInactive:= false;
    60 Gear.Y:= Gear.Y + cDrownSpeed;
    61 Gear^.Y:= Gear^.Y + cDrownSpeed;
    61 if round(Gear.Y) > Gear.Radius + cWaterLine + cVisibleWater then DeleteGear(Gear)
    62 if hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater then DeleteGear(Gear)
    62 end;
    63 end;
    63 
    64 
    64 ////////////////////////////////////////////////////////////////////////////////
    65 ////////////////////////////////////////////////////////////////////////////////
    65 procedure doStepFallingGear(Gear: PGear);
    66 procedure doStepFallingGear(Gear: PGear);
    66 var b: boolean;
    67 var b: boolean;
    67 begin
    68 begin
    68 if TestCollisionYwithGear(Gear, hwSign(Gear.dY)) then
    69 if TestCollisionYwithGear(Gear, hwSign(Gear^.dY)) then
    69    begin
    70    begin
    70    Gear.dX:=   Gear.dX * Gear.Friction;
    71    Gear^.dX:=   Gear^.dX * Gear^.Friction;
    71    Gear.dY:= - Gear.dY * Gear.Elasticity;
    72    Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
    72    b:= false
    73    b:= false
    73    end else b:= true;
    74    end else b:= true;
    74 if TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then
    75 if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
    75    begin
    76    begin
    76    Gear.dX:= - Gear.dX * Gear.Elasticity;
    77    Gear^.dX:= - Gear^.dX * Gear^.Elasticity;
    77 //   Gear.dY:=   Gear.dY;
    78 //   Gear^.dY:=   Gear^.dY;
    78    b:= false
    79    b:= false
    79    end;
    80    end;
    80 if b then
    81 if b then
    81    begin
    82    begin
    82    Gear.dY:= Gear.dY + cGravity;
    83    Gear^.dY:= Gear^.dY + cGravity;
    83    Gear.State:= Gear.State and not gstCollision
    84    Gear^.State:= Gear^.State and not gstCollision
    84    end else
    85    end else
    85    begin
    86    begin
    86    if sqr(Gear.dX) + sqr(Gear.dY) < 0.00001 then
    87    if hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _1div100000 then
    87       if (Gear.Timer = 0) then Gear.Active:= false
    88       if (Gear^.Timer = 0) then Gear^.Active:= false
    88                           else begin
    89                           else begin
    89                           Gear.dX:= 0;
    90                           Gear^.dX:= 0;
    90                           Gear.dY:= 0
    91                           Gear^.dY:= 0
    91                           end;
    92                           end;
    92    Gear.State:= Gear.State or gstCollision
    93    Gear^.State:= Gear^.State or gstCollision
    93    end;
    94    end;
    94 Gear.X:= Gear.X + Gear.dX;
    95 Gear^.X:= Gear^.X + Gear^.dX;
    95 Gear.Y:= Gear.Y + Gear.dY;
    96 Gear^.Y:= Gear^.Y + Gear^.dY;
    96 CheckGearDrowning(Gear);
    97 CheckGearDrowning(Gear);
    97 if (sqr(Gear.dX) + sqr(Gear.dY) < 0.003) then Gear.State:= Gear.State and not gstMoving
    98 if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _0_003) then Gear^.State:= Gear^.State and not gstMoving
    98                                          else Gear.State:= Gear.State or      gstMoving
    99                                          else Gear^.State:= Gear^.State or      gstMoving
    99 end;
   100 end;
   100 
   101 
   101 ////////////////////////////////////////////////////////////////////////////////
   102 ////////////////////////////////////////////////////////////////////////////////
   102 procedure doStepCloud(Gear: PGear);
   103 procedure doStepCloud(Gear: PGear);
   103 begin
   104 begin
   104 Gear.X:= Gear.X + cWindSpeed * 200 + Gear.dX;
   105 Gear^.X:= Gear^.X + cWindSpeed * 200 + Gear^.dX;
   105 if Gear.Y > -160 then Gear.dY:= Gear.dY - 0.00002
   106 if Gear^.Y > -160 then Gear^.dY:= Gear^.dY - _1div50000
   106                  else Gear.dY:= Gear.dY + 0.00002;
   107                  else Gear^.dY:= Gear^.dY + _1div50000;
   107 Gear.Y:= Gear.Y + Gear.dY;
   108 Gear^.Y:= Gear^.Y + Gear^.dY;
   108 if Gear.X < -cScreenWidth - 256 then Gear.X:= cScreenWidth + 2048 else
   109 if Gear^.X < -cScreenWidth - 256 then Gear^.X:= cScreenWidth + 2048 else
   109 if Gear.X > cScreenWidth + 2048 then Gear.X:= -cScreenWidth - 256
   110 if Gear^.X > cScreenWidth + 2048 then Gear^.X:= -cScreenWidth - 256
   110 end;
   111 end;
   111 
   112 
   112 ////////////////////////////////////////////////////////////////////////////////
   113 ////////////////////////////////////////////////////////////////////////////////
   113 procedure doStepBomb(Gear: PGear);
   114 procedure doStepBomb(Gear: PGear);
   114 var i: integer;
   115 var i: integer;
   115 begin
   116 begin
   116 AllInactive:= false;
   117 AllInactive:= false;
   117 doStepFallingGear(Gear);
   118 doStepFallingGear(Gear);
   118 dec(Gear.Timer);
   119 dec(Gear^.Timer);
   119 if Gear.Timer = 0 then
   120 if Gear^.Timer = 0 then
   120    begin
   121    begin
   121    case Gear.Kind of
   122    case Gear^.Kind of
   122         gtAmmo_Bomb: doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
   123         gtAmmo_Bomb: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   123       gtClusterBomb: begin
   124       gtClusterBomb: begin
   124                      doMakeExplosion(round(Gear.X), round(Gear.Y), 30, EXPLAutoSound);
   125                      doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
   125                      for i:= 0 to 4 do
   126                      for i:= 0 to 4 do
   126                          AddGear(round(Gear.X), round(Gear.Y), gtCluster, 0, (getrandom - 0.5)*0.2, (getrandom - 3) * 0.08);
   127                          AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, (getrandom - _0_5) * _0_2, (getrandom - 3) * _0_08, 0);
   127                      end
   128                      end
   128         end;
   129         end;
   129    DeleteGear(Gear);
   130    DeleteGear(Gear);
   130    exit
   131    exit
   131    end;
   132    end;
   132 CalcRotationDirAngle(Gear);
   133 CalcRotationDirAngle(Gear);
   133 if (Gear.State and (gstCollision or gstMoving)) = (gstCollision or gstMoving) then PlaySound(sndGrenadeImpact)
   134 if (Gear^.State and (gstCollision or gstMoving)) = (gstCollision or gstMoving) then PlaySound(sndGrenadeImpact, false)
   134 end;
   135 end;
   135 
   136 
   136 procedure doStepCluster(Gear: PGear);
   137 procedure doStepCluster(Gear: PGear);
   137 begin
   138 begin
   138 AllInactive:= false;
   139 AllInactive:= false;
   139 doStepFallingGear(Gear);
   140 doStepFallingGear(Gear);
   140 if (Gear.State and gstCollision) <> 0 then
   141 if (Gear^.State and gstCollision) <> 0 then
   141    begin
   142    begin
   142    doMakeExplosion(round(Gear.X), round(Gear.Y), 20, EXPLAutoSound);
   143    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, EXPLAutoSound);
   143    DeleteGear(Gear);
   144    DeleteGear(Gear);
   144    exit
   145    exit
   145    end;
   146    end;
   146 if (GameTicks and $1F) = 0 then
   147 if (GameTicks and $1F) = 0 then
   147    AddGear(round(Gear.X), round(Gear.Y), gtSmokeTrace, 0)
   148    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, 0, 0, 0)
   148 end;
   149 end;
   149 
   150 
   150 ////////////////////////////////////////////////////////////////////////////////
   151 ////////////////////////////////////////////////////////////////////////////////
   151 procedure doStepGrenade(Gear: PGear);
   152 procedure doStepGrenade(Gear: PGear);
   152 begin
   153 begin
   153 AllInactive:= false;
   154 AllInactive:= false;
   154 Gear.dX:= Gear.dX + cWindSpeed;
   155 Gear^.dX:= Gear^.dX + cWindSpeed;
   155 doStepFallingGear(Gear);
   156 doStepFallingGear(Gear);
   156 if (Gear.State and gstCollision) <> 0 then
   157 if (Gear^.State and gstCollision) <> 0 then
   157    begin
   158    begin
   158    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
   159    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   159    DeleteGear(Gear);
   160    DeleteGear(Gear);
   160    exit
   161    exit
   161    end;
   162    end;
   162 if (GameTicks and $3F) = 0 then
   163 if (GameTicks and $3F) = 0 then
   163    AddGear(round(Gear.X), round(Gear.Y), gtSmokeTrace, 0)
   164    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, 0, 0, 0)
   164 end;
   165 end;
   165 
   166 
   166 ////////////////////////////////////////////////////////////////////////////////
   167 ////////////////////////////////////////////////////////////////////////////////
   167 procedure doStepHealthTagWork(Gear: PGear);
   168 procedure doStepHealthTagWork(Gear: PGear);
   168 begin
   169 begin
   169 AllInactive:= false;
   170 AllInactive:= false;
   170 dec(Gear.Timer);
   171 dec(Gear^.Timer);
   171 Gear.Y:= Gear.Y - 0.07;
   172 Gear^.Y:= Gear^.Y - _0_08;
   172 if Gear.Timer = 0 then
   173 if Gear^.Timer = 0 then
   173    begin
   174    begin
   174    PHedgehog(Gear.Hedgehog).Gear.Active:= true; // to let current hh die
   175    PHedgehog(Gear^.Hedgehog)^.Gear^.Active:= true; // to let current hh die
   175    DeleteGear(Gear)
   176    DeleteGear(Gear)
   176    end
   177    end
   177 end;
   178 end;
   178 
   179 
   179 procedure doStepHealthTagWorkUnderWater(Gear: PGear);
   180 procedure doStepHealthTagWorkUnderWater(Gear: PGear);
   180 begin
   181 begin
   181 AllInactive:= false;
   182 AllInactive:= false;
   182 Gear.Y:= Gear.Y - 0.07;
   183 Gear^.Y:= Gear^.Y - _0_08;
   183 if Gear.Y <= cWaterLine + 10 then
   184 if Gear^.Y < cWaterLine + 10 then
   184    DeleteGear(Gear)
   185    DeleteGear(Gear)
   185 end;
   186 end;
   186 
   187 
   187 procedure doStepHealthTag(Gear: PGear);
   188 procedure doStepHealthTag(Gear: PGear);
   188 var s: shortstring;
   189 var s: shortstring;
   189 begin
   190 begin
   190 AllInactive:= false;
   191 AllInactive:= false;
   191 str(Gear.State, s);
   192 str(Gear^.State, s);
   192 Gear.Surf:= RenderString(s, PHedgehog(Gear.Hedgehog).Team.Color, fnt16);
   193 Gear^.Surf:= RenderString(s, PHedgehog(Gear^.Hedgehog)^.Team^.Color, fnt16);
   193 if Gear.Y < cWaterLine then Gear.doStep:= doStepHealthTagWork
   194 if Gear^.Y < cWaterLine then Gear^.doStep:= @doStepHealthTagWork
   194                        else Gear.doStep:= doStepHealthTagWorkUnderWater
   195                        else Gear^.doStep:= @doStepHealthTagWorkUnderWater
   195 end;
   196 end;
   196 
   197 
   197 ////////////////////////////////////////////////////////////////////////////////
   198 ////////////////////////////////////////////////////////////////////////////////
   198 procedure doStepGrave(Gear: PGear);
   199 procedure doStepGrave(Gear: PGear);
   199 begin
   200 begin
   200 AllInactive:= false;
   201 AllInactive:= false;
   201 if Gear.dY < 0 then
   202 if Gear^.dY < 0 then
   202    if TestCollisionY(Gear, -1) then Gear.dY:= 0;
   203    if TestCollisionY(Gear, -1) then Gear^.dY:= 0;
   203 
   204 
   204 if Gear.dY >=0 then
   205 if not Gear^.dY.isNegative then
   205    if TestCollisionY(Gear, 1) then
   206    if TestCollisionY(Gear, 1) then
   206       begin
   207       begin
   207       Gear.dY:= - Gear.dY * Gear.Elasticity;
   208       Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
   208       if Gear.dY > - 0.001 then
   209       if Gear^.dY > - _1div1024 then
   209          begin
   210          begin
   210          Gear.Active:= false;
   211          Gear^.Active:= false;
   211          exit
   212          exit
   212          end else if Gear.dY < - 0.03 then PlaySound(sndGraveImpact)
   213          end else if Gear^.dY < - _0_03 then PlaySound(sndGraveImpact, false)
   213       end;
   214       end;
   214 Gear.Y:= Gear.Y + Gear.dY;
   215 Gear^.Y:= Gear^.Y + Gear^.dY;
   215 CheckGearDrowning(Gear);
   216 CheckGearDrowning(Gear);
   216 Gear.dY:= Gear.dY + cGravity
   217 Gear^.dY:= Gear^.dY + cGravity
   217 end;
   218 end;
   218 
   219 
   219 ////////////////////////////////////////////////////////////////////////////////
   220 ////////////////////////////////////////////////////////////////////////////////
   220 procedure doStepUFOWork(Gear: PGear);
   221 procedure doStepUFOWork(Gear: PGear);
   221 var t: Double;
   222 var t: hwFloat;
   222 begin
   223 begin
   223 AllInactive:= false;
   224 AllInactive:= false;
   224 t:= sqrt(sqr(Gear.dX) + sqr(Gear.dY));
   225 t:= Distance(Gear^.dX, Gear^.dY);
   225 Gear.dX:= Gear.Elasticity * (Gear.dX + 0.000004 * (TargetPoint.X - trunc(Gear.X)));
   226 Gear^.dX:= Gear^.Elasticity * (Gear^.dX + _0_000004 * (TargetPoint.X - hwRound(Gear^.X)));
   226 Gear.dY:= Gear.Elasticity * (Gear.dY + 0.000004 * (TargetPoint.Y - trunc(Gear.Y)));
   227 Gear^.dY:= Gear^.Elasticity * (Gear^.dY + _0_000004 * (TargetPoint.Y - hwRound(Gear^.Y)));
   227 t:= t / (sqrt(sqr(Gear.dX) + sqr(Gear.dY)));
   228 t:= t / Distance(Gear^.dX, Gear^.dY);
   228 Gear.dX:= Gear.dX * t;
   229 Gear^.dX:= Gear^.dX * t;
   229 Gear.dY:= Gear.dY * t;
   230 Gear^.dY:= Gear^.dY * t;
   230 Gear.X:= Gear.X + Gear.dX;
   231 Gear^.X:= Gear^.X + Gear^.dX;
   231 Gear.Y:= Gear.Y + Gear.dY;
   232 Gear^.Y:= Gear^.Y + Gear^.dY;
   232 CheckCollision(Gear);
   233 CheckCollision(Gear);
   233 dec(Gear.Timer);
   234 dec(Gear^.Timer);
   234 if ((Gear.State and gstCollision) <> 0) or (Gear.Timer = 0) then
   235 if ((Gear^.State and gstCollision) <> 0) or (Gear^.Timer = 0) then
   235    begin
   236    begin
   236    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
   237    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   237    DeleteGear(Gear);
   238    DeleteGear(Gear);
   238    end;
   239    end;
   239 end;
   240 end;
   240 
   241 
   241 procedure doStepUFO(Gear: PGear);
   242 procedure doStepUFO(Gear: PGear);
   242 begin
   243 begin
   243 AllInactive:= false;
   244 AllInactive:= false;
   244 Gear.X:= Gear.X + Gear.dX;
   245 Gear^.X:= Gear^.X + Gear^.dX;
   245 Gear.Y:= Gear.Y + Gear.dY;
   246 Gear^.Y:= Gear^.Y + Gear^.dY;
   246 Gear.dY:= Gear.dY + cGravity;
   247 Gear^.dY:= Gear^.dY + cGravity;
   247 CheckCollision(Gear);
   248 CheckCollision(Gear);
   248 if (Gear.State and gstCollision) <> 0 then
   249 if (Gear^.State and gstCollision) <> 0 then
   249    begin
   250    begin
   250    doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
   251    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   251    DeleteGear(Gear);
   252    DeleteGear(Gear);
   252    exit
   253    exit
   253    end;
   254    end;
   254 dec(Gear.Timer);
   255 dec(Gear^.Timer);
   255 if Gear.Timer = 0 then
   256 if Gear^.Timer = 0 then
   256    begin
   257    begin
   257    Gear.Timer:= 5000;
   258    Gear^.Timer:= 5000;
   258    Gear.doStep:= doStepUFOWork
   259    Gear^.doStep:= @doStepUFOWork
   259    end;
   260    end;
   260 end;
   261 end;
   261 
   262 
   262 ////////////////////////////////////////////////////////////////////////////////
   263 ////////////////////////////////////////////////////////////////////////////////
   263 procedure doStepShotgunShot(Gear: PGear);
   264 procedure doStepShotgunShot(Gear: PGear);
   264 var i: LongWord;
   265 var i: LongWord;
   265 begin
   266 begin
   266 AllInactive:= false;
   267 AllInactive:= false;
   267 if Gear.Timer > 0 then
   268 if Gear^.Timer > 0 then
   268    begin
   269    begin
   269    dec(Gear.Timer);
   270    dec(Gear^.Timer);
   270    if Gear.Timer = 0 then PlaySound(sndShotgunFire);
   271    if Gear^.Timer = 0 then PlaySound(sndShotgunFire, false);
   271    exit
   272    exit
   272    end;
   273    end;
   273 i:= 200;
   274 i:= 200;
   274 repeat
   275 repeat
   275 Gear.X:= Gear.X + Gear.dX;
   276 Gear^.X:= Gear^.X + Gear^.dX;
   276 Gear.Y:= Gear.Y + Gear.dY;
   277 Gear^.Y:= Gear^.Y + Gear^.dY;
   277 CheckCollision(Gear);
   278 CheckCollision(Gear);
   278 if (Gear.State and gstCollision) <> 0 then
   279 if (Gear^.State and gstCollision) <> 0 then
   279    begin
   280    begin
   280    AmmoShove(Gear, 25, 25);
   281    AmmoShove(Gear, 25, 25);
   281    doMakeExplosion(round(Gear.X), round(Gear.Y), 25, EXPLNoDamage or EXPLDoNotTouchHH);
   282    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, EXPLNoDamage or EXPLDoNotTouchHH);
   282    DeleteGear(Gear);
   283    DeleteGear(Gear);
   283    AfterAttack;
   284    AfterAttack;
   284    exit
   285    exit
   285    end;
   286    end;
   286 dec(i)
   287 dec(i)
   287 until i = 0;
   288 until i = 0;
   288 if (Gear.X < 0) or (Gear.Y < 0) or (Gear.X > 2048) or (Gear.Y > 1024) then
   289 if (Gear^.X < 0) or (Gear^.Y < 0) or (Gear^.X > 2048) or (Gear^.Y > 1024) then
   289    begin
   290    begin
   290    DeleteGear(Gear);
   291    DeleteGear(Gear);
   291    AfterAttack
   292    AfterAttack
   292    end
   293    end
   293 end;
   294 end;
   294 
   295 
   295 ////////////////////////////////////////////////////////////////////////////////
   296 ////////////////////////////////////////////////////////////////////////////////
   296 procedure doStepDEagleShot(Gear: PGear);
   297 procedure doStepDEagleShot(Gear: PGear);
   297 var i, x, y: LongWord;
   298 var i, x, y: LongWord;
   298     oX, oY: Double;
   299     oX, oY: hwFloat;
   299 begin
   300 begin
   300 AllInactive:= false;
   301 AllInactive:= false;
   301 i:= 80;
   302 i:= 80;
   302 oX:= Gear.X;
   303 oX:= Gear^.X;
   303 oY:= Gear.Y;
   304 oY:= Gear^.Y;
   304 repeat
   305 repeat
   305   Gear.X:= Gear.X + Gear.dX;
   306   Gear^.X:= Gear^.X + Gear^.dX;
   306   Gear.Y:= Gear.Y + Gear.dY;
   307   Gear^.Y:= Gear^.Y + Gear^.dY;
   307   x:= round(Gear.X);
   308   x:= hwRound(Gear^.X);
   308   y:= round(Gear.Y);
   309   y:= hwRound(Gear^.Y);
   309   if ((y and $FFFFFC00) = 0) and ((x and $FFFFF800) = 0)
   310   if ((y and $FFFFFC00) = 0) and ((x and $FFFFF800) = 0)
   310      and (Land[y, x] <> 0) then inc(Gear.Damage);
   311      and (Land[y, x] <> 0) then inc(Gear^.Damage);
   311   AmmoShove(Gear, 7, 20);
   312   AmmoShove(Gear, 7, 20);
   312   dec(i)
   313   dec(i)
   313 until (i = 0) or (Gear.Damage > Gear.Health);
   314 until (i = 0) or (Gear^.Damage > Gear^.Health);
   314 if Gear.Damage > 0 then
   315 if Gear^.Damage > 0 then
   315    begin
   316    begin
   316    DrawTunnel(oX, oY, Gear.dX, Gear.dY, 82 - i, 1);
   317    DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
   317    dec(Gear.Health, Gear.Damage);
   318    dec(Gear^.Health, Gear^.Damage);
   318    Gear.Damage:= 0
   319    Gear^.Damage:= 0
   319    end;
   320    end;
   320 if (Gear.Health <= 0) or (Gear.X < 0) or (Gear.Y < 0) or (Gear.X > 2048) or (Gear.Y > 1024) then
   321 if (Gear^.Health <= 0) or (Gear^.X < 0) or (Gear^.Y < 0) or (Gear^.X > 2048) or (Gear^.Y > 1024) then
   321    DeleteGear(Gear)
   322    DeleteGear(Gear)
   322 end;
   323 end;
   323 
   324 
   324 ////////////////////////////////////////////////////////////////////////////////
   325 ////////////////////////////////////////////////////////////////////////////////
   325 procedure doStepActionTimer(Gear: PGear);
   326 procedure doStepActionTimer(Gear: PGear);
   326 begin
   327 begin
   327 dec(Gear.Timer);
   328 dec(Gear^.Timer);
   328 case Gear.Kind of
   329 case Gear^.Kind of
   329     gtATStartGame: begin
   330     gtATStartGame: begin
   330                    AllInactive:= false;
   331                    AllInactive:= false;
   331                    if Gear.Timer = 0 then
   332                    if Gear^.Timer = 0 then
   332                       AddCaption(trmsg[sidStartFight], $FFFFFF, capgrpGameState);
   333                       AddCaption(trmsg[sidStartFight], $FFFFFF, capgrpGameState);
   333                    end;
   334                    end;
   334  gtATSmoothWindCh: begin
   335  gtATSmoothWindCh: begin
   335                    if Gear.Timer = 0 then
   336                    if Gear^.Timer = 0 then
   336                       begin
   337                       begin
   337                       if WindBarWidth < Gear.Tag then inc(WindBarWidth)
   338                       if WindBarWidth < Gear^.Tag then inc(WindBarWidth)
   338                          else if WindBarWidth > Gear.Tag then dec(WindBarWidth);
   339                          else if WindBarWidth > Gear^.Tag then dec(WindBarWidth);
   339                       if WindBarWidth <> Gear.Tag then Gear.Timer:= 10;
   340                       if WindBarWidth <> Gear^.Tag then Gear^.Timer:= 10;
   340                       end
   341                       end
   341                    end;
   342                    end;
   342    gtATFinishGame: begin
   343    gtATFinishGame: begin
   343                    AllInactive:= false;
   344                    AllInactive:= false;
   344                    if Gear.Timer = 0 then
   345                    if Gear^.Timer = 0 then
   345                       begin
   346                       begin
   346                       SendIPC('N');
   347                       SendIPC('N');
   347                       SendIPC('q');
   348                       SendIPC('q');
   348                       GameState:= gsExit
   349                       GameState:= gsExit
   349                       end
   350                       end
   350                    end;
   351                    end;
   351      end;
   352      end;
   352 if Gear.Timer = 0 then DeleteGear(Gear)
   353 if Gear^.Timer = 0 then DeleteGear(Gear)
   353 end;
   354 end;
   354 
   355 
   355 ////////////////////////////////////////////////////////////////////////////////
   356 ////////////////////////////////////////////////////////////////////////////////
   356 procedure doStepPickHammerWork(Gear: PGear);
   357 procedure doStepPickHammerWork(Gear: PGear);
   357 var i, ei: integer;
   358 var i, ei: integer;
   358     HHGear: PGear;
   359     HHGear: PGear;
   359 begin
   360 begin
   360 AllInactive:= false;
   361 AllInactive:= false;
   361 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   362 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   362 dec(Gear.Timer);
   363 dec(Gear^.Timer);
   363 if (Gear.Timer = 0)or((Gear.Message and gm_Destroy) <> 0)or((HHGear.State and gstHHDriven) = 0) then
   364 if (Gear^.Timer = 0)or((Gear^.Message and gm_Destroy) <> 0)or((HHGear^.State and gstHHDriven) = 0) then
   364    begin
   365    begin
   365    StopSound(sndPickhammer);
   366    StopSound(sndPickhammer);
   366    DeleteGear(Gear);
   367    DeleteGear(Gear);
   367    AfterAttack;
   368    AfterAttack;
   368    exit
   369    exit
   369    end;
   370    end;
   370 if (Gear.Timer and $3F) = 0 then
   371 if (Gear^.Timer and $3F) = 0 then
   371    begin
   372    begin
   372    i:= round(Gear.X) - Gear.Radius  - GetRandom(2);
   373    i:= hwRound(Gear^.X) - Gear^.Radius  - GetRandom(2);
   373    ei:= round(Gear.X) + Gear.Radius + GetRandom(2);
   374    ei:= hwRound(Gear^.X) + Gear^.Radius + GetRandom(2);
   374    while i <= ei do
   375    while i <= ei do
   375          begin
   376          begin
   376          doMakeExplosion(i, round(Gear.Y) + 3, 3, 0);
   377          doMakeExplosion(i, hwRound(Gear^.Y) + 3, 3, 0);
   377          inc(i, 1)
   378          inc(i, 1)
   378          end;
   379          end;
   379    Gear.X:= Gear.X + Gear.dX;
   380    Gear^.X:= Gear^.X + Gear^.dX;
   380    Gear.Y:= Gear.Y + 1.9;
   381    Gear^.Y:= Gear^.Y + _1_9;
   381    SetAllHHToActive;
   382    SetAllHHToActive;
   382    end;
   383    end;
   383 if TestCollisionYwithGear(Gear, 1) then
   384 if TestCollisionYwithGear(Gear, 1) then
   384    begin
   385    begin
   385    Gear.dY:= 0;
   386    Gear^.dY:= 0;
   386    SetLittle(HHGear.dX);
   387    SetLittle(HHGear^.dX);
   387    HHGear.dY:= 0;
   388    HHGear^.dY:= 0;
   388    end else
   389    end else
   389    begin
   390    begin
   390    Gear.dY:= Gear.dY + cGravity;
   391    Gear^.dY:= Gear^.dY + cGravity;
   391    Gear.Y:= Gear.Y + Gear.dY;
   392    Gear^.Y:= Gear^.Y + Gear^.dY;
   392    if Gear.Y > 1024 then Gear.Timer:= 1
   393    if Gear^.Y > 1024 then Gear^.Timer:= 1
   393    end;
   394    end;
   394 
   395 
   395 Gear.X:= Gear.X + HHGear.dX;
   396 Gear^.X:= Gear^.X + HHGear^.dX;
   396 HHGear.X:= Gear.X;
   397 HHGear^.X:= Gear^.X;
   397 HHGear.Y:= Gear.Y - cHHRadius;
   398 HHGear^.Y:= Gear^.Y - cHHRadius;
   398 
   399 
   399 if (Gear.Message and gm_Attack) <> 0 then
   400 if (Gear^.Message and gm_Attack) <> 0 then
   400    if (Gear.State and gsttmpFlag) <> 0 then Gear.Timer:= 1 else else
   401    if (Gear^.State and gsttmpFlag) <> 0 then Gear^.Timer:= 1 else else
   401    if (Gear.State and gsttmpFlag) = 0 then Gear.State:= Gear.State or gsttmpFlag;
   402    if (Gear^.State and gsttmpFlag) = 0 then Gear^.State:= Gear^.State or gsttmpFlag;
   402 if ((Gear.Message and gm_Left) <> 0) then Gear.dX:= -0.3 else
   403 if ((Gear^.Message and gm_Left) <> 0) then Gear^.dX:= - _0_3 else
   403    if ((Gear.Message and gm_Right) <> 0) then Gear.dX:= 0.3
   404    if ((Gear^.Message and gm_Right) <> 0) then Gear^.dX:= _0_3
   404                                          else Gear.dX:= 0;
   405                                          else Gear^.dX:= 0;
   405 end;
   406 end;
   406 
   407 
   407 procedure doStepPickHammer(Gear: PGear);
   408 procedure doStepPickHammer(Gear: PGear);
   408 var i, y: integer;
   409 var i, y: integer;
   409     ar: TRangeArray;
   410     ar: TRangeArray;
   410 begin
   411 begin
   411 i:= 0;
   412 i:= 0;
   412 y:= round(Gear.Y) - cHHRadius*2;
   413 y:= hwRound(Gear^.Y) - cHHRadius*2;
   413 while y < round(Gear.Y) do
   414 while y < hwRound(Gear^.Y) do
   414    begin
   415    begin
   415    ar[i].Left := round(Gear.X) - Gear.Radius - GetRandom(2);
   416    ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - GetRandom(2);
   416    ar[i].Right:= round(Gear.X) + Gear.Radius + GetRandom(2);
   417    ar[i].Right:= hwRound(Gear^.X) + Gear^.Radius + GetRandom(2);
   417    inc(y, 2);
   418    inc(y, 2);
   418    inc(i)
   419    inc(i)
   419    end;
   420    end;
   420 DrawHLinesExplosions(@ar, 3, round(Gear.Y) - cHHRadius*2, 2, Pred(i));
   421 DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius*2, 2, Pred(i));
   421 Gear.dY:= PHedgehog(Gear.Hedgehog).Gear.dY;
   422 Gear^.dY:= PHedgehog(Gear^.Hedgehog)^.Gear^.dY;
   422 PlaySound(sndPickhammer, true);
   423 PlaySound(sndPickhammer, true);
   423 doStepPickHammerWork(Gear);
   424 doStepPickHammerWork(Gear);
   424 Gear.doStep:= doStepPickHammerWork
   425 Gear^.doStep:= @doStepPickHammerWork
   425 end;
   426 end;
   426 
   427 
   427 ////////////////////////////////////////////////////////////////////////////////
   428 ////////////////////////////////////////////////////////////////////////////////
   428 var BTPrevAngle, BTSteps: Longword;
   429 var BTPrevAngle, BTSteps: Longword;
   429 
   430 
   430 procedure doStepBlowTorchWork(Gear: PGear);
   431 procedure doStepBlowTorchWork(Gear: PGear);
   431 var HHGear: PGear;
   432 var HHGear: PGear;
   432     b: boolean;
   433     b: boolean;
   433 begin
   434 begin
   434 AllInactive:= false;
   435 AllInactive:= false;
   435 dec(Gear.Timer);
   436 dec(Gear^.Timer);
   436 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   437 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   437 
   438 
   438 HedgehogChAngle(HHGear);
   439 HedgehogChAngle(HHGear);
   439 
   440 
   440 b:= false;
   441 b:= false;
   441 
   442 
   442 if (HHGear.Angle <> BTPrevAngle) then
   443 if (HHGear^.Angle <> BTPrevAngle) then
   443    begin
   444    begin
   444    Gear.dX:= hwSign(HHGear.dX) * Sin(HHGear.Angle * pi / cMaxAngle) * 0.5;
   445    Gear^.dX:= hwSign(HHGear^.dX) * _0_5;//hwSign(HHGear^.dX) * Sin(HHGear^.Angle * pi / cMaxAngle) * _0_5;
   445    Gear.dY:= Cos(HHGear.Angle * pi / cMaxAngle) * (-0.5);
   446    Gear^.dY:= 0;//Cos(HHGear^.Angle * pi / cMaxAngle) * (-0.5);
   446    BTPrevAngle:= HHGear.Angle;
   447    BTPrevAngle:= HHGear^.Angle;
   447    b:= true
   448    b:= true
   448    end;
   449    end;
   449 
   450 
   450 if Gear.Timer mod cHHStepTicks = 0 then
   451 if Gear^.Timer mod cHHStepTicks = 0 then
   451    begin
   452    begin
   452    b:= true;
   453    b:= true;
   453    if Gear.dX < 0 then HHGear.Message:= (HHGear.Message or gm_Left) and not gm_Right
   454    if Gear^.dX < 0 then HHGear^.Message:= (HHGear^.Message or gm_Left) and not gm_Right
   454                   else HHGear.Message:= (HHGear.Message or gm_Right) and not gm_Left;
   455                   else HHGear^.Message:= (HHGear^.Message or gm_Right) and not gm_Left;
   455    HedgehogStep(HHGear);
   456    HedgehogStep(HHGear);
   456 
   457 
   457    inc(BTSteps);
   458    inc(BTSteps);
   458    if BTSteps = 11 then
   459    if BTSteps = 11 then
   459       begin
   460       begin
   460       BTSteps:= 0;
   461       BTSteps:= 0;
   461       Gear.X:= HHGear.X + Gear.dX * cHHRadius * 2;
   462       Gear^.X:= HHGear^.X + Gear^.dX * cHHRadius * 2;
   462       Gear.Y:= HHGear.Y + Gear.dY * cHHRadius * 2;
   463       Gear^.Y:= HHGear^.Y + Gear^.dY * cHHRadius * 2;
   463       HHGear.State:= HHGear.State or gstNoDamage;
   464       HHGear^.State:= HHGear^.State or gstNoDamage;
   464       AmmoShove(Gear, 3, 14);
   465       AmmoShove(Gear, 3, 14);
   465       HHGear.State:= HHGear.State and not gstNoDamage
   466       HHGear^.State:= HHGear^.State and not gstNoDamage
   466       end;
   467       end;
   467 
   468 
   468    if (HHGear.State and gstFalling) <> 0 then Gear.Timer:= 0
   469    if (HHGear^.State and gstFalling) <> 0 then Gear^.Timer:= 0
   469    end;
   470    end;
   470 
   471 
   471 if b then
   472 if b then
   472    DrawTunnel(HHGear.X - Gear.dX * cHHRadius, HHGear.Y - 4 - Gear.dY * cHHRadius + abs(Gear.dY) * 7,
   473    DrawTunnel(HHGear^.X - Gear^.dX * cHHRadius, HHGear^.Y - 4 - Gear^.dY * cHHRadius + hwAbs(Gear^.dY) * 7,
   473               Gear.dX, Gear.dY,
   474               Gear^.dX, Gear^.dY,
   474               cHHRadius * 5, cHHRadius * 2 + 6);
   475               cHHRadius * 5, cHHRadius * 2 + 6);
   475 
   476 
   476 if (Gear.Timer = 0) or ((HHGear.Message and gm_Attack) <> 0) then
   477 if (Gear^.Timer = 0) or ((HHGear^.Message and gm_Attack) <> 0) then
   477    begin
   478    begin
   478    HHGear.Message:= 0;
   479    HHGear^.Message:= 0;
   479    DeleteGear(Gear);
   480    DeleteGear(Gear);
   480    AfterAttack
   481    AfterAttack
   481    end
   482    end
   482 end;
   483 end;
   483 
   484 
   484 procedure doStepBlowTorch(Gear: PGear);
   485 procedure doStepBlowTorch(Gear: PGear);
   485 var HHGear: PGear;
   486 var HHGear: PGear;
   486 begin
   487 begin
   487 BTPrevAngle:= High(Longword);
   488 BTPrevAngle:= High(Longword);
   488 BTSteps:= 0;
   489 BTSteps:= 0;
   489 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   490 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   490 HHGear.State:= HHGear.State and not gstAttacking;
   491 HHGear^.State:= HHGear^.State and not gstAttacking;
   491 HHGear.Message:= 0;
   492 HHGear^.Message:= 0;
   492 Gear.doStep:= doStepBlowTorchWork
   493 Gear^.doStep:= @doStepBlowTorchWork
   493 end;
   494 end;
   494 
   495 
   495 ////////////////////////////////////////////////////////////////////////////////
   496 ////////////////////////////////////////////////////////////////////////////////
   496 
   497 
   497 procedure doStepRopeWork(Gear: PGear);
   498 procedure doStepRopeWork(Gear: PGear);
   498 const flCheck: boolean = false;
   499 const flCheck: boolean = false;
   499 var HHGear: PGear;
   500 var HHGear: PGear;
   500     len, cs, cc, tx, ty: Double;
   501     len, cs, cc, tx, ty: hwFloat;
   501     lx, ly: LongInt;
   502     lx, ly: LongInt;
   502 
   503 
   503     procedure DeleteMe;
   504     procedure DeleteMe;
   504     begin
   505     begin
   505       with HHGear^ do
   506       with HHGear^ do
   506            begin
   507            begin
   507            Message:= Message and not gm_Attack;
   508            Message:= Message and not gm_Attack;
   508            State:= State or gstFalling;
   509            State:= State or gstFalling;
   509            end;
   510            end;
   510       DeleteGear(Gear);
   511       DeleteGear(Gear);
   511       OnUsedAmmo(PHedgehog(HHGear.Hedgehog)^.Ammo);
   512       OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^.Ammo);
   512       ApplyAmmoChanges(PHedgehog(HHGear.Hedgehog)^)
   513       ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^)
   513     end;
   514     end;
   514 
   515 
   515 begin
   516 begin
   516 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   517 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   517 
   518 
   518 if ((HHGear.State and gstHHDriven) = 0)
   519 if ((HHGear^.State and gstHHDriven) = 0)
   519    or (CheckGearDrowning(HHGear)) then
   520    or (CheckGearDrowning(HHGear)) then
   520    begin
   521    begin
   521    DeleteMe;
   522    DeleteMe;
   522    exit
   523    exit
   523    end;
   524    end;
   524 Gear.dX:= HHGear.X - Gear.X;
   525 Gear^.dX:= HHGear^.X - Gear^.X;
   525 Gear.dY:= HHGear.Y - Gear.Y;
   526 Gear^.dY:= HHGear^.Y - Gear^.Y;
   526 
   527 
   527 if (Gear.Message and gm_Left  <> 0) then HHGear.dX:= HHGear.dX - 0.0002 else
   528 if (Gear^.Message and gm_Left  <> 0) then HHGear^.dX:= HHGear^.dX - _0_0002 else
   528 if (Gear.Message and gm_Right <> 0) then HHGear.dX:= HHGear.dX + 0.0002;
   529 if (Gear^.Message and gm_Right <> 0) then HHGear^.dX:= HHGear^.dX + _0_0002;
   529 
   530 
   530 if not TestCollisionYwithGear(HHGear, 1) then HHGear.dY:= HHGear.dY + cGravity;
   531 if not TestCollisionYwithGear(HHGear, 1) then HHGear^.dY:= HHGear^.dY + cGravity;
   531 
   532 
   532 cs:= Gear.dY + HHGear.dY;
   533 cs:= Gear^.dY + HHGear^.dY;
   533 cc:= Gear.dX + HHGear.dX;
   534 cc:= Gear^.dX + HHGear^.dX;
   534 len:= 1 / sqrt(sqr(cc)+sqr(cs));
   535 len:= 1 / Distance(cc, cs);
   535 cc:= cc * len;
   536 cc:= cc * len;
   536 cs:= cs * len;
   537 cs:= cs * len;
   537 
   538 
   538 flCheck:= not flCheck;
   539 flCheck:= not flCheck;
   539 if flCheck then  // check whether rope needs dividing
   540 if flCheck then  // check whether rope needs dividing
   540    begin
   541    begin
   541    len:= Gear.Elasticity - 20;
   542    len:= Gear^.Elasticity - 20;
   542    while len > 5 do
   543    while len > 5 do
   543          begin
   544          begin
   544          tx:= cc*len;
   545          tx:= cc*len;
   545          ty:= cs*len;
   546          ty:= cs*len;
   546          lx:= round(Gear.X + tx) + hwSign(HHGear.dX);
   547          lx:= hwRound(Gear^.X + tx) + hwSign(HHGear^.dX);
   547          ly:= round(Gear.Y + ty) + hwSign(HHGear.dY);
   548          ly:= hwRound(Gear^.Y + ty) + hwSign(HHGear^.dY);
   548          if ((ly and $FFFFFC00) = 0) and ((lx and $FFFFF800) = 0)and (Land[ly, lx] <> 0) then
   549          if ((ly and $FFFFFC00) = 0) and ((lx and $FFFFF800) = 0)and (Land[ly, lx] <> 0) then
   549            begin
   550            begin
   550            with RopePoints.ar[RopePoints.Count] do
   551            with RopePoints.ar[RopePoints.Count] do
   551                 begin
   552                 begin
   552                 X:= Gear.X;
   553                 X:= Gear^.X;
   553                 Y:= Gear.Y;
   554                 Y:= Gear^.Y;
   554                 if RopePoints.Count = 0 then RopePoints.HookAngle:= DxDy2Angle32(Gear.dY, Gear.dX);
   555                 if RopePoints.Count = 0 then RopePoints.HookAngle:= 0;//DxDy2Angle32(Gear^.dY, Gear^.dX);
   555                 b:= (cc * HHGear.dY) > (cs * HHGear.dX);
   556                 b:= (cc * HHGear^.dY) > (cs * HHGear^.dX);
   556                 dLen:= len
   557                 dLen:= len
   557                 end;
   558                 end;
   558            Gear.X:= Gear.X + tx;
   559            Gear^.X:= Gear^.X + tx;
   559            Gear.Y:= Gear.Y + ty;
   560            Gear^.Y:= Gear^.Y + ty;
   560            inc(RopePoints.Count);
   561            inc(RopePoints.Count);
   561            Gear.Elasticity:= Gear.Elasticity - len;
   562            Gear^.Elasticity:= Gear^.Elasticity - len;
   562            Gear.Friction:= Gear.Friction - len;
   563            Gear^.Friction:= Gear^.Friction - len;
   563            break
   564            break
   564            end;
   565            end;
   565          len:= len - 3
   566          len:= len - 3
   566          end;
   567          end;
   567    end else
   568    end else
   568    if RopePoints.Count > 0 then // check whether the last dividing point could be removed
   569    if RopePoints.Count > 0 then // check whether the last dividing point could be removed
   569       begin
   570       begin
   570       tx:= RopePoints.ar[Pred(RopePoints.Count)].X;
   571       tx:= RopePoints.ar[Pred(RopePoints.Count)].X;
   571       ty:= RopePoints.ar[Pred(RopePoints.Count)].Y;
   572       ty:= RopePoints.ar[Pred(RopePoints.Count)].Y;
   572       if GameTicks = 189245 then
   573       if RopePoints.ar[Pred(RopePoints.Count)].b xor ((tx - Gear^.X) * (ty - HHGear^.Y) > (tx - HHGear^.X) * (ty - Gear^.Y)) then
   573          begin
       
   574          AddFileLog('tx = ' + floattostr(tx) + ' ty = ' + floattostr(ty));
       
   575          AddFileLog('Gear.X = ' + floattostr(Gear.X) + ' Gear.Y = ' + floattostr(Gear.Y));
       
   576          AddFileLog('HHGear.X = ' + floattostr(HHGear.X) + ' HHGear.Y = ' + floattostr(HHGear.Y));
       
   577          end;
       
   578       if RopePoints.ar[Pred(RopePoints.Count)].b xor ((tx - Gear.X) * (ty - HHGear.Y) > (tx - HHGear.X) * (ty - Gear.Y)) then
       
   579          begin
   574          begin
   580          dec(RopePoints.Count);
   575          dec(RopePoints.Count);
   581          Gear.X:=RopePoints.ar[RopePoints.Count].X;
   576          Gear^.X:=RopePoints.ar[RopePoints.Count].X;
   582          Gear.Y:=RopePoints.ar[RopePoints.Count].Y;
   577          Gear^.Y:=RopePoints.ar[RopePoints.Count].Y;
   583          Gear.Elasticity:= Gear.Elasticity + RopePoints.ar[RopePoints.Count].dLen;
   578          Gear^.Elasticity:= Gear^.Elasticity + RopePoints.ar[RopePoints.Count].dLen;
   584          Gear.Friction:= Gear.Friction + RopePoints.ar[RopePoints.Count].dLen
   579          Gear^.Friction:= Gear^.Friction + RopePoints.ar[RopePoints.Count].dLen
   585          end
   580          end
   586       end;
   581       end;
   587 
   582 
   588 Gear.dX:= HHGear.X - Gear.X;
   583 Gear^.dX:= HHGear^.X - Gear^.X;
   589 Gear.dY:= HHGear.Y - Gear.Y;
   584 Gear^.dY:= HHGear^.Y - Gear^.Y;
   590 
   585 
   591 cs:= Gear.dY + HHGear.dY;
   586 cs:= Gear^.dY + HHGear^.dY;
   592 cc:= Gear.dX + HHGear.dX;
   587 cc:= Gear^.dX + HHGear^.dX;
   593 len:= 1 / sqrt(sqr(cc)+sqr(cs));
   588 len:= 1 / Distance(cc, cs);
   594 cc:= cc * len;
   589 cc:= cc * len;
   595 cs:= cs * len;
   590 cs:= cs * len;
   596 
   591 
   597 HHGear.dX:= HHGear.X;
   592 HHGear^.dX:= HHGear^.X;
   598 HHGear.dY:= HHGear.Y;
   593 HHGear^.dY:= HHGear^.Y;
   599 
   594 
   600 if ((Gear.Message and gm_Down) <> 0) and (Gear.Elasticity < Gear.Friction) then
   595 if ((Gear^.Message and gm_Down) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
   601    if not (TestCollisionXwithGear(HHGear, hwSign(Gear.dX))
   596    if not (TestCollisionXwithGear(HHGear, hwSign(Gear^.dX))
   602         or TestCollisionYwithGear(HHGear, hwSign(Gear.dY))) then Gear.Elasticity:= Gear.Elasticity + 0.3;
   597         or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY))) then Gear^.Elasticity:= Gear^.Elasticity + _0_3;
   603 
   598 
   604 if ((Gear.Message and gm_Up) <> 0) and (Gear.Elasticity > 30) then
   599 if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Elasticity > 30) then
   605    if not (TestCollisionXwithGear(HHGear, -hwSign(Gear.dX))
   600    if not (TestCollisionXwithGear(HHGear, -hwSign(Gear^.dX))
   606         or TestCollisionYwithGear(HHGear, -hwSign(Gear.dY))) then Gear.Elasticity:= Gear.Elasticity - 0.3;
   601         or TestCollisionYwithGear(HHGear, -hwSign(Gear^.dY))) then Gear^.Elasticity:= Gear^.Elasticity - _0_3;
   607 
   602 
   608 HHGear.X:= Gear.X + cc*Gear.Elasticity;
   603 HHGear^.X:= Gear^.X + cc*Gear^.Elasticity;
   609 HHGear.Y:= Gear.Y + cs*Gear.Elasticity;
   604 HHGear^.Y:= Gear^.Y + cs*Gear^.Elasticity;
   610 
   605 
   611 HHGear.dX:= HHGear.X - HHGear.dX;
   606 HHGear^.dX:= HHGear^.X - HHGear^.dX;
   612 HHGear.dY:= HHGear.Y - HHGear.dY;
   607 HHGear^.dY:= HHGear^.Y - HHGear^.dY;
   613 
   608 
   614 if TestCollisionXwithGear(HHGear, hwSign(HHGear.dX)) then
   609 if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
   615    HHGear.dX:= -0.6 * HHGear.dX;
   610    HHGear^.dX:= -_0_6 * HHGear^.dX;
   616 if TestCollisionYwithGear(HHGear, hwSign(HHGear.dY)) then
   611 if TestCollisionYwithGear(HHGear, hwSign(HHGear^.dY)) then
   617    HHGear.dY:= -0.6 * HHGear.dY;
   612    HHGear^.dY:= -_0_6 * HHGear^.dY;
   618 
   613 
   619 if (Gear.Message and gm_Attack) <> 0 then
   614 if (Gear^.Message and gm_Attack) <> 0 then
   620    if (Gear.State and gsttmpFlag) <> 0 then DeleteMe else
   615    if (Gear^.State and gsttmpFlag) <> 0 then DeleteMe else
   621 else if (Gear.State and gsttmpFlag) = 0 then Gear.State:= Gear.State or gsttmpFlag;
   616 else if (Gear^.State and gsttmpFlag) = 0 then Gear^.State:= Gear^.State or gsttmpFlag;
   622 end;
   617 end;
   623 
   618 
   624 
   619 
   625 procedure doStepRopeAttach(Gear: PGear);
   620 procedure doStepRopeAttach(Gear: PGear);
   626 var HHGear: PGear;
   621 var HHGear: PGear;
   627     tx, ty, tt: Double;
   622     tx, ty, tt: hwFloat;
   628 begin
   623 begin
   629 Gear.X:= Gear.X - Gear.dX;
   624 Gear^.X:= Gear^.X - Gear^.dX;
   630 Gear.Y:= Gear.Y - Gear.dY;
   625 Gear^.Y:= Gear^.Y - Gear^.dY;
   631 Gear.Elasticity:= Gear.Elasticity + 1.0;
   626 Gear^.Elasticity:= Gear^.Elasticity + 1;
   632 HHGear:= PHedgehog(Gear.Hedgehog)^.Gear;
   627 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   633 if (HHGear.State and gstFalling) <> 0 then
   628 if (HHGear^.State and gstFalling) <> 0 then
   634    if TestCollisionYwithGear(HHGear, 1) then
   629    if TestCollisionYwithGear(HHGear, 1) then
   635       begin
   630       begin
   636       HHGear.dY:= 0;
   631       HHGear^.dY:= 0;
   637       CheckHHDamage(HHGear);
   632       CheckHHDamage(HHGear);
   638       HHGear.State:= HHGear.State and not (gstFalling or gstHHJumping);
   633       HHGear^.State:= HHGear^.State and not (gstFalling or gstHHJumping);
   639       end else
   634       end else
   640       begin
   635       begin
   641       if TestCollisionXwithGear(HHGear, hwSign(HHGear.dX)) then HHGear.dX:= 0.0000001 * hwSign(HHGear.dX);
   636       if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
   642       HHGear.X:= HHGear.X + HHGear.dX;
   637       HHGear^.X:= HHGear^.X + HHGear^.dX;
   643       HHGear.Y:= HHGear.Y + HHGear.dY;
   638       HHGear^.Y:= HHGear^.Y + HHGear^.dY;
   644       Gear.X:= Gear.X + HHGear.dX;
   639       Gear^.X:= Gear^.X + HHGear^.dX;
   645       Gear.Y:= Gear.Y + HHGear.dY;
   640       Gear^.Y:= Gear^.Y + HHGear^.dY;
   646       HHGear.dY:= HHGear.dY + cGravity;
   641       HHGear^.dY:= HHGear^.dY + cGravity;
   647       tt:= Gear.Elasticity;
   642       tt:= Gear^.Elasticity;
   648       tx:= 0;
   643       tx:= 0;
   649       ty:= 0;
   644       ty:= 0;
   650       while tt > 20 do
   645       while tt > 20 do
   651             begin
   646             begin
   652             if  TestCollisionXwithXYShift(Gear, round(tx), round(ty), hwSign(Gear.dX))
   647             if  TestCollisionXwithXYShift(Gear, hwRound(tx), hwRound(ty), hwSign(Gear^.dX))
   653              or TestCollisionYwithXYShift(Gear, round(tx), round(ty), hwSign(Gear.dY)) then
   648              or TestCollisionYwithXYShift(Gear, hwRound(tx), hwRound(ty), hwSign(Gear^.dY)) then
   654                 begin
   649                 begin
   655                 Gear.X:= Gear.X + tx;
   650                 Gear^.X:= Gear^.X + tx;
   656                 Gear.Y:= Gear.Y + ty;
   651                 Gear^.Y:= Gear^.Y + ty;
   657                 Gear.Elasticity:= tt;
   652                 Gear^.Elasticity:= tt;
   658                 Gear.doStep:= doStepRopeWork;
   653                 Gear^.doStep:= @doStepRopeWork;
   659                 with HHGear^ do State:= State and not gstAttacking;
   654                 with HHGear^ do State:= State and not gstAttacking;
   660                 tt:= 0
   655                 tt:= 0
   661                 end;
   656                 end;
   662             tx:= tx + Gear.dX - Gear.dX;
   657             tx:= tx + Gear^.dX - Gear^.dX;
   663             ty:= ty + Gear.dY - Gear.dY;
   658             ty:= ty + Gear^.dY - Gear^.dY;
   664             tt:= tt - 2.0;
   659             tt:= tt - 2;
   665             end;
   660             end;
   666       end;
   661       end;
   667 CheckCollision(Gear);
   662 CheckCollision(Gear);
   668 if (Gear.State and gstCollision) <> 0 then
   663 if (Gear^.State and gstCollision) <> 0 then
   669    begin
   664    begin
   670    Gear.doStep:= doStepRopeWork;
   665    Gear^.doStep:= @doStepRopeWork;
   671    with HHGear^ do State:= State and not gstAttacking;
   666    with HHGear^ do State:= State and not gstAttacking;
   672    if Gear.Elasticity < 10 then
   667    if Gear^.Elasticity < 10 then
   673       Gear.Elasticity:= 10000;
   668       Gear^.Elasticity:= 10000;
   674    end;
   669    end;
   675 
   670 
   676 if (Gear.Elasticity >= Gear.Friction) or ((Gear.Message and gm_Attack) = 0) then
   671 if (Gear^.Elasticity > Gear^.Friction) or ((Gear^.Message and gm_Attack) = 0) then
   677    begin
   672    begin
   678    with PHedgehog(Gear.Hedgehog).Gear^ do
   673    with PHedgehog(Gear^.Hedgehog)^.Gear^ do
   679         begin
   674         begin
   680         State:= State and not gstAttacking;
   675         State:= State and not gstAttacking;
   681         Message:= Message and not gm_Attack
   676         Message:= Message and not gm_Attack
   682         end;
   677         end;
   683    DeleteGear(Gear)
   678    DeleteGear(Gear)
   684    end
   679    end
   685 end;
   680 end;
   686 
   681 
   687 procedure doStepRope(Gear: PGear);
   682 procedure doStepRope(Gear: PGear);
   688 begin
   683 begin
   689 Gear.dX:= - Gear.dX;
   684 Gear^.dX:= - Gear^.dX;
   690 Gear.dY:= - Gear.dY;
   685 Gear^.dY:= - Gear^.dY;
   691 Gear.doStep:= doStepRopeAttach
   686 Gear^.doStep:= @doStepRopeAttach
   692 end;
   687 end;
   693 
   688 
   694 ////////////////////////////////////////////////////////////////////////////////
   689 ////////////////////////////////////////////////////////////////////////////////
   695 procedure doStepSmokeTrace(Gear: PGear);
   690 procedure doStepSmokeTrace(Gear: PGear);
   696 begin
   691 begin
   697 inc(Gear.Timer);
   692 inc(Gear^.Timer);
   698 if Gear.Timer > 64 then
   693 if Gear^.Timer > 64 then
   699    begin
   694    begin
   700    Gear.Timer:= 0;
   695    Gear^.Timer:= 0;
   701    dec(Gear.State)
   696    dec(Gear^.State)
   702    end;
   697    end;
   703 Gear.dX:= Gear.dX + cWindSpeed;
   698 Gear^.dX:= Gear^.dX + cWindSpeed;
   704 Gear.X:= Gear.X + Gear.dX;
   699 Gear^.X:= Gear^.X + Gear^.dX;
   705 if Gear.State = 0 then DeleteGear(Gear)
   700 if Gear^.State = 0 then DeleteGear(Gear)
   706 end;
   701 end;
   707 
   702 
   708 ////////////////////////////////////////////////////////////////////////////////
   703 ////////////////////////////////////////////////////////////////////////////////
   709 procedure doStepExplosion(Gear: PGear);
   704 procedure doStepExplosion(Gear: PGear);
   710 begin
   705 begin
   711 inc(Gear.Timer);
   706 inc(Gear^.Timer);
   712 if Gear.Timer > 75 then
   707 if Gear^.Timer > 75 then
   713    begin
   708    begin
   714    inc(Gear.State);
   709    inc(Gear^.State);
   715    Gear.Timer:= 0;
   710    Gear^.Timer:= 0;
   716    if Gear.State > 5 then DeleteGear(Gear)
   711    if Gear^.State > 5 then DeleteGear(Gear)
   717    end;
   712    end;
   718 end;
   713 end;
   719 
   714 
   720 ////////////////////////////////////////////////////////////////////////////////
   715 ////////////////////////////////////////////////////////////////////////////////
   721 procedure doStepMine(Gear: PGear);
   716 procedure doStepMine(Gear: PGear);
   722 begin
   717 begin
   723 if (Gear.dX <> 0) or (Gear.dY <> 0) then
   718 if (Gear^.dX.QWordValue <> 0) or (Gear^.dY.QWordValue <> 0) then
   724    begin
   719    begin
   725    if Gear.CollIndex < High(Longword) then DeleteCI(Gear);
   720    if Gear^.CollIndex < High(Longword) then DeleteCI(Gear);
   726    doStepFallingGear(Gear);
   721    doStepFallingGear(Gear);
   727    if Gear.Active = false then
   722    if Gear^.Active = false then
   728       begin
   723       begin
   729       if Gear.CollIndex = High(Longword) then AddGearCI(Gear);
   724       if Gear^.CollIndex = High(Longword) then AddGearCI(Gear);
   730       Gear.dX:= 0;
   725       Gear^.dX:= 0;
   731       Gear.dY:= 0
   726       Gear^.dY:= 0
   732       end;
   727       end;
   733    CalcRotationDirAngle(Gear);
   728    CalcRotationDirAngle(Gear);
   734    AllInactive:= false
   729    AllInactive:= false
   735    end;
   730    end;
   736    
   731 
   737 if ((Gear.State and gsttmpFlag) <> 0) then
   732 if ((Gear^.State and gsttmpFlag) <> 0) then
   738    if ((Gear.State and gstAttacking) = 0) then
   733    if ((Gear^.State and gstAttacking) = 0) then
   739       begin
   734       begin
   740       if ((GameTicks and $F) = 0) then
   735       if ((GameTicks and $F) = 0) then
   741          if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then Gear.State:= Gear.State or gstAttacking
   736          if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then Gear^.State:= Gear^.State or gstAttacking
   742       end else // gstAttacking <> 0
   737       end else // gstAttacking <> 0
   743       begin
   738       begin
   744       AllInactive:= false;
   739       AllInactive:= false;
   745       if (Gear.Timer and $FF) = 0 then PlaySound(sndMineTick);
   740       if (Gear^.Timer and $FF) = 0 then PlaySound(sndMineTick, false);
   746       if Gear.Timer = 0 then
   741       if Gear^.Timer = 0 then
   747          begin
   742          begin
   748          doMakeExplosion(round(Gear.X), round(Gear.Y), 50, EXPLAutoSound);
   743          doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, EXPLAutoSound);
   749          DeleteGear(Gear)
   744          DeleteGear(Gear)
   750          end;
   745          end;
   751       dec(Gear.Timer);
   746       dec(Gear^.Timer);
   752       end else // gsttmpFlag = 0
   747       end else // gsttmpFlag = 0
   753    if TurnTimeLeft = 0 then Gear.State:= Gear.State or gsttmpFlag;
   748    if TurnTimeLeft = 0 then Gear^.State:= Gear^.State or gsttmpFlag;
   754 end;
   749 end;
   755 
   750 
   756 ////////////////////////////////////////////////////////////////////////////////
   751 ////////////////////////////////////////////////////////////////////////////////
   757 procedure doStepDynamite(Gear: PGear);
   752 procedure doStepDynamite(Gear: PGear);
   758 begin
   753 begin
   759 doStepFallingGear(Gear);
   754 doStepFallingGear(Gear);
   760 AllInactive:= false;
   755 AllInactive:= false;
   761 if Gear.Timer mod 166 = 0 then inc(Gear.Tag);
   756 if Gear^.Timer mod 166 = 0 then inc(Gear^.Tag);
   762 if Gear.Timer = 0 then
   757 if Gear^.Timer = 0 then
   763    begin
   758    begin
   764    doMakeExplosion(round(Gear.X), round(Gear.Y), 75, EXPLAutoSound);
   759    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 75, EXPLAutoSound);
   765    DeleteGear(Gear);
   760    DeleteGear(Gear);
   766    exit
   761    exit
   767    end;
   762    end;
   768 dec(Gear.Timer);
   763 dec(Gear^.Timer);
   769 end;
   764 end;
   770 
   765 
   771 ////////////////////////////////////////////////////////////////////////////////
   766 ///////////////////////////////////////////////////////////////////////////////
   772 procedure doStepCase(Gear: PGear);
   767 procedure doStepCase(Gear: PGear);
   773 var i, x, y: integer;
   768 var i, x, y: integer;
   774 begin
   769 begin
   775 if (Gear.Message and gm_Destroy) > 0 then
   770 if (Gear^.Message and gm_Destroy) > 0 then
   776    begin
   771    begin
   777    DeleteGear(Gear);
   772    DeleteGear(Gear);
   778    exit
   773    exit
   779    end;
   774    end;
   780 
   775 
   781 if Gear.Damage > 0 then
   776 if Gear^.Damage > 0 then
   782    begin
   777    begin
   783    x:= round(Gear.X);
   778    x:= hwRound(Gear^.X);
   784    y:= round(Gear.Y);
   779    y:= hwRound(Gear^.Y);
   785    DeleteGear(Gear);
   780    DeleteGear(Gear);
   786    doMakeExplosion(x, y, 25, EXPLAutoSound);
   781    doMakeExplosion(x, y, 25, EXPLAutoSound);
   787    for i:= 0 to 63 do
   782    for i:= 0 to 63 do
   788        AddGear(x, y, gtFlame, 0);
   783        AddGear(x, y, gtFlame, 0, 0, 0, 0);
   789    exit
   784    exit
   790    end;
   785    end;
   791 
   786 
   792 if (Gear.dY <> 0) or (not TestCollisionYwithGear(Gear, 1)) then
   787 if (Gear^.dY.QWordValue <> 0) or (not TestCollisionYwithGear(Gear, 1)) then
   793    begin
   788    begin
   794    AllInactive:= false;
   789    AllInactive:= false;
   795    Gear.dY:= Gear.dY + cGravity;
   790    Gear^.dY:= Gear^.dY + cGravity;
   796    Gear.Y:= Gear.Y + Gear.dY;
   791    Gear^.Y:= Gear^.Y + Gear^.dY;
   797    if (Gear.dY < 0) and TestCollisionYwithGear(Gear, -1) then Gear.dY:= 0 else
   792    if (Gear^.dY.isNegative) and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= 0 else
   798    if (Gear.dY >= 0) and TestCollisionYwithGear(Gear, 1) then
   793    if (Gear^.dY.QWordValue <> 0) and TestCollisionYwithGear(Gear, 1) then
   799       begin
   794       begin
   800       Gear.dY:= - Gear.dY * Gear.Elasticity;
   795       Gear^.dY:= - Gear^.dY * Gear^.Elasticity;
   801       if Gear.dY > - 0.001 then Gear.dY:= 0
   796       if Gear^.dY > - _0_001 then Gear^.dY:= 0
   802          else if Gear.dY < - 0.03 then PlaySound(sndGraveImpact);
   797          else if Gear^.dY < - _0_03 then PlaySound(sndGraveImpact, false);
   803       end;
   798       end;
   804    CheckGearDrowning(Gear);
   799    CheckGearDrowning(Gear);
   805    end;
   800    end;
   806 
   801 
   807 if (Gear.CollIndex = High(Longword)) and (Gear.dY = 0) then AddGearCI(Gear)
   802 if (Gear^.CollIndex = High(Longword)) and (Gear^.dY.QWordValue = 0) then AddGearCI(Gear)
   808    else if (Gear.CollIndex < High(Longword)) and (Gear.dY <> 0) then DeleteCI(Gear);
   803    else if (Gear^.CollIndex < High(Longword)) and (Gear^.dY.QWordValue <> 0) then DeleteCI(Gear);
   809 end;
   804 end;
   810 
   805 
   811 ////////////////////////////////////////////////////////////////////////////////
   806 ////////////////////////////////////////////////////////////////////////////////
   812 var thexchar: array[0..5] of record
   807 var thexchar: array[0..5] of record
   813                              oy, ny: integer;
   808                              oy, ny: integer;
   818 
   813 
   819 procedure doStepTeamHealthSorterWork(Gear: PGear);
   814 procedure doStepTeamHealthSorterWork(Gear: PGear);
   820 var i: integer;
   815 var i: integer;
   821 begin
   816 begin
   822 AllInactive:= false;
   817 AllInactive:= false;
   823 dec(Gear.Timer);
   818 dec(Gear^.Timer);
   824 if (Gear.Timer and 15) = 0 then
   819 if (Gear^.Timer and 15) = 0 then
   825    for i:= 0 to Pred(thexchcnt) do
   820    for i:= 0 to Pred(thexchcnt) do
   826        with thexchar[i] do
   821        with thexchar[i] do
   827             {$WARNINGS OFF}
   822             {$WARNINGS OFF}
   828             team.DrawHealthY:= ny + (oy - ny) * Gear.Timer div 640;
   823             team^.DrawHealthY:= ny + (oy - ny) * Gear^.Timer div 640;
   829             {$WARNINGS ON}
   824             {$WARNINGS ON}
   830 if (Gear.Timer = 0) or (currsorter <> Gear) then
   825 if (Gear^.Timer = 0) or (currsorter <> Gear) then
   831    begin
   826    begin
   832    if currsorter = Gear then currsorter:= nil;
   827    if currsorter = Gear then currsorter:= nil;
   833    DeleteGear(Gear)
   828    DeleteGear(Gear)
   834    end
   829    end
   835 end;
   830 end;
   841 AllInactive:= false;
   836 AllInactive:= false;
   842 team:= TeamsList;
   837 team:= TeamsList;
   843 i:= 0;
   838 i:= 0;
   844 while team <> nil do
   839 while team <> nil do
   845       begin
   840       begin
   846       thexchar[i].oy:= team.DrawHealthY;
   841       thexchar[i].oy:= team^.DrawHealthY;
   847       thexchar[i].team:= team;
   842       thexchar[i].team:= team;
   848       inc(i);
   843       inc(i);
   849       team:= team.Next
   844       team:= team^.Next
   850       end;
   845       end;
   851 thexchcnt:= i;
   846 thexchcnt:= i;
   852 for i:= 1 to thexchcnt do
   847 for i:= 1 to thexchcnt do
   853     for t:= 0 to thexchcnt - 2 do
   848     for t:= 0 to thexchcnt - 2 do
   854         if thexchar[t].team.TeamHealthBarWidth > thexchar[Succ(t)].team.TeamHealthBarWidth then
   849         if thexchar[t].team^.TeamHealthBarWidth > thexchar[Succ(t)].team^.TeamHealthBarWidth then
   855            begin
   850            begin
   856            thexchar[5]:= thexchar[t];
   851            thexchar[5]:= thexchar[t];
   857            thexchar[t]:= thexchar[Succ(t)];
   852            thexchar[t]:= thexchar[Succ(t)];
   858            thexchar[Succ(t)]:= thexchar[5]
   853            thexchar[Succ(t)]:= thexchar[5]
   859            end;
   854            end;
   860 t:= cScreenHeight - 4;
   855 t:= cScreenHeight - 4;
   861 for i:= 0 to Pred(thexchcnt) do
   856 for i:= 0 to Pred(thexchcnt) do
   862     with thexchar[i] do
   857     with thexchar[i] do
   863          begin
   858          begin
   864          dec(t, team.HealthRect.h + 2);
   859          dec(t, team^.HealthRect.h + 2);
   865          ny:= t
   860          ny:= t
   866          end;
   861          end;
   867 Gear.Timer:= 640;
   862 Gear^.Timer:= 640;
   868 Gear.doStep:= doStepTeamHealthSorterWork;
   863 Gear^.doStep:= @doStepTeamHealthSorterWork;
   869 currsorter:= Gear
   864 currsorter:= Gear
   870 end;
   865 end;
   871 
   866 
   872 ////////////////////////////////////////////////////////////////////////////////
   867 ////////////////////////////////////////////////////////////////////////////////
   873 procedure doStepShover(Gear: PGear);
   868 procedure doStepShover(Gear: PGear);
   874 var HHGear: PGear;
   869 var HHGear: PGear;
   875 begin
   870 begin
   876 HHGear:= PHedgehog(Gear.Hedgehog)^.Gear;
   871 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   877 HHGear.State:= HHGear.State or gstNoDamage;
   872 HHGear^.State:= HHGear^.State or gstNoDamage;
   878 AmmoShove(Gear, 30, 115);
   873 AmmoShove(Gear, 30, 115);
   879 HHGear.State:= HHGear.State and not gstNoDamage;
   874 HHGear^.State:= HHGear^.State and not gstNoDamage;
   880 DeleteGear(Gear)
   875 DeleteGear(Gear)
   881 end;
   876 end;
   882 
   877 
   883 ////////////////////////////////////////////////////////////////////////////////
   878 ////////////////////////////////////////////////////////////////////////////////
   884 procedure doStepFlame(Gear: PGear);
   879 procedure doStepFlame(Gear: PGear);
   885 begin
   880 begin
   886 AllInactive:= false;
   881 AllInactive:= false;
   887 if not TestCollisionYwithGear(Gear, 1) then
   882 if not TestCollisionYwithGear(Gear, 1) then
   888    begin
   883    begin
   889    Gear.dX:= Gear.dX + cWindSpeed;
   884    Gear^.dX:= Gear^.dX + cWindSpeed;
   890    Gear.dY:= Gear.dY + cGravity;
   885    Gear^.dY:= Gear^.dY + cGravity;
   891    if abs(Gear.dX) > 0.12 then Gear.dX:= Gear.dX * 0.5;
   886    if hwAbs(Gear^.dX) > _0_1 then Gear^.dX:= Gear^.dX * _0_5;
   892    if Gear.dY > 0.12 then Gear.dY:= Gear.dY * 0.995;
   887    if Gear^.dY > _0_1 then Gear^.dY:= Gear^.dY * _0_995;
   893    Gear.X:= Gear.X + Gear.dX;
   888    Gear^.X:= Gear^.X + Gear^.dX;
   894    Gear.Y:= Gear.Y + Gear.dY;
   889    Gear^.Y:= Gear^.Y + Gear^.dY;
   895    if Gear.Y > 1023 then
   890    if Gear^.Y > 1023 then
   896       begin
   891       begin
   897       DeleteGear(Gear);
   892       DeleteGear(Gear);
   898       exit
   893       exit
   899       end
   894       end
   900    end else begin
   895    end else begin
   901    if Gear.Timer > 0 then dec(Gear.Timer)
   896    if Gear^.Timer > 0 then dec(Gear^.Timer)
   902       else begin
   897       else begin
   903       doMakeExplosion(round(Gear.X), round(Gear.Y), 2, 0);
   898       doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 2, 0);
   904       dec(Gear.Health);
   899       dec(Gear^.Health);
   905       Gear.Timer:= 1250 - Gear.Angle * 12
   900       Gear^.Timer:= 1250 - Gear^.Angle * 12
   906       end
   901       end
   907    end;
   902    end;
   908 
   903 
   909 if (((GameTicks div 8) mod 64) = Gear.Angle) then
   904 if (((GameTicks div 8) mod 64) = Gear^.Angle) then
   910    AmmoFlameWork(Gear);
   905    AmmoFlameWork(Gear);
   911 
   906 
   912 if Gear.Health = 0 then
   907 if Gear^.Health = 0 then
   913    DeleteGear(Gear)
   908    DeleteGear(Gear)
   914 end;
   909 end;
   915 
   910 
   916 ////////////////////////////////////////////////////////////////////////////////
   911 ////////////////////////////////////////////////////////////////////////////////
   917 procedure doStepFirePunchWork(Gear: PGear);
   912 procedure doStepFirePunchWork(Gear: PGear);
   918 var HHGear: PGear;
   913 var HHGear: PGear;
   919 begin
   914 begin
   920 AllInactive:= false;
   915 AllInactive:= false;
   921 if ((Gear.Message and gm_Destroy) <> 0) then
   916 if ((Gear^.Message and gm_Destroy) <> 0) then
   922    begin
   917    begin
   923    DeleteGear(Gear);
   918    DeleteGear(Gear);
   924    AfterAttack;
   919    AfterAttack;
   925    exit
   920    exit
   926    end;
   921    end;
   927 
   922 
   928 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   923 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   929 if round(HHGear.Y) <= Gear.Tag - 2 then
   924 if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then
   930    begin
   925    begin
   931    Gear.Tag:= round(HHGear.Y);
   926    Gear^.Tag:= hwRound(HHGear^.Y);
   932    DrawTunnel(HHGear.X - cHHRadius, HHGear.Y - 1, 0.5, 0.0, cHHRadius * 4, 2);
   927    DrawTunnel(HHGear^.X - cHHRadius, HHGear^.Y - 1, _0_5, 0, cHHRadius * 4, 2);
   933    HHGear.State:= HHGear.State or gstNoDamage;
   928    HHGear^.State:= HHGear^.State or gstNoDamage;
   934    Gear.Y:= HHGear.Y;
   929    Gear^.Y:= HHGear^.Y;
   935    AmmoShove(Gear, 30, 40);
   930    AmmoShove(Gear, 30, 40);
   936    HHGear.State:= HHGear.State and not gstNoDamage
   931    HHGear^.State:= HHGear^.State and not gstNoDamage
   937    end;
   932    end;
   938    
   933 
   939 HHGear.dY:= HHGear.dY + cGravity;
   934 HHGear^.dY:= HHGear^.dY + cGravity;
   940 if HHGear.dY >= 0 then
   935 if not (HHGear^.dY.isNegative) then
   941    begin
   936    begin
   942    HHGear.State:= HHGear.State or gstFalling;
   937    HHGear^.State:= HHGear^.State or gstFalling;
   943    DeleteGear(Gear);
   938    DeleteGear(Gear);
   944    AfterAttack;
   939    AfterAttack;
   945    exit
   940    exit
   946    end;
   941    end;
   947 HHGear.Y:= HHGear.Y + HHGear.dY
   942 HHGear^.Y:= HHGear^.Y + HHGear^.dY
   948 end;
   943 end;
   949 
   944 
   950 procedure doStepFirePunch(Gear: PGear);
   945 procedure doStepFirePunch(Gear: PGear);
   951 var HHGear: PGear;
   946 var HHGear: PGear;
   952 begin
   947 begin
   953 AllInactive:= false;
   948 AllInactive:= false;
   954 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   949 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   955 HHGear.X:= round(HHGear.X) - 0.5;
   950 HHGear^.X:= hwRound(HHGear^.X) - _0_5;
   956 HHGear.dX:= 0.0000001 * hwSign(HHGear.dX);
   951 SetLittle(HHGear^.dX);
   957 HHGear.dY:= -0.30;
   952 HHGear^.dY:= - _0_3;
   958 
   953 
   959 Gear.X:= HHGear.X;
   954 Gear^.X:= HHGear^.X;
   960 Gear.dX:= hwSign(HHGear.dX)* 0.45;
   955 Gear^.dX:= hwSign(HHGear^.dX) * _0_45;
   961 Gear.dY:= -0.9;
   956 Gear^.dY:= - _0_9;
   962 Gear.doStep:= doStepFirePunchWork;
   957 Gear^.doStep:= @doStepFirePunchWork;
   963 DrawTunnel(HHGear.X - cHHRadius, HHGear.Y + 1, 0.5, 0.0, cHHRadius * 4, 5);
   958 DrawTunnel(HHGear^.X - cHHRadius, HHGear^.Y + 1, _0_5, 0, cHHRadius * 4, 5);
   964 end;
   959 end;
   965 
   960 
   966 ////////////////////////////////////////////////////////////////////////////////
   961 ////////////////////////////////////////////////////////////////////////////////
   967 
   962 
   968 procedure doStepParachute(Gear: PGear);
   963 procedure doStepParachute(Gear: PGear);
   969 var HHGear: PGear;
   964 var HHGear: PGear;
   970 begin
   965 begin
   971 HHGear:= PHedgehog(Gear.Hedgehog).Gear;
   966 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
   972 HHGear.State:= HHGear.State and not gstAttacking;
   967 HHGear^.State:= HHGear^.State and not gstAttacking;
   973 
   968 
   974 if TestCollisionYwithGear(HHGear, 1)
   969 if TestCollisionYwithGear(HHGear, 1)
   975    or ((HHGear.State and gstHHDriven) = 0)
   970    or ((HHGear^.State and gstHHDriven) = 0)
   976    or CheckGearDrowning(HHGear) then
   971    or CheckGearDrowning(HHGear) then
   977    begin
   972    begin
   978    with HHGear^ do
   973    with HHGear^ do
   979         begin
   974         begin
   980         Message:= 0;
   975         Message:= 0;
   981         dx:= 0.0000001 * hwSign(dX);
   976         SetLittle(dx);
   982         dY:= 0;
   977         dY:= 0;
   983         State:= State and not (gstAttacking or gstAttacked);
   978         State:= State and not (gstAttacking or gstAttacked);
   984         State:= State or gstFalling;
   979         State:= State or gstFalling;
   985         end;
   980         end;
   986    DeleteGear(Gear);
   981    DeleteGear(Gear);
   987    OnUsedAmmo(PHedgehog(HHGear.Hedgehog)^.Ammo);
   982    OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^.Ammo);
   988    ApplyAmmoChanges(PHedgehog(HHGear.Hedgehog)^);
   983    ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
   989    exit
   984    exit
   990    end;
   985    end;
   991 
   986 
   992 if not TestCollisionXwithGear(HHGear, hwSign(HHGear.dX)) then
   987 if not TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
   993    HHGear.X:= HHGear.X + cWindSpeed * 200;
   988    HHGear^.X:= HHGear^.X + cWindSpeed * 200;
   994 
   989 
   995 if (Gear.Message and gm_Left) <> 0 then HHGear.X:= HHGear.X - cMaxWindSpeed * 40
   990 if (Gear^.Message and gm_Left) <> 0 then HHGear^.X:= HHGear^.X - cMaxWindSpeed * 40
   996 else if (Gear.Message and gm_Right) <> 0 then HHGear.X:= HHGear.X + cMaxWindSpeed * 40;
   991 else if (Gear^.Message and gm_Right) <> 0 then HHGear^.X:= HHGear^.X + cMaxWindSpeed * 40;
   997 if (Gear.Message and gm_Up) <> 0 then HHGear.Y:= HHGear.Y - cGravity * 40
   992 if (Gear^.Message and gm_Up) <> 0 then HHGear^.Y:= HHGear^.Y - cGravity * 40
   998 else if (Gear.Message and gm_Down) <> 0 then HHGear.Y:= HHGear.Y + cGravity * 40;
   993 else if (Gear^.Message and gm_Down) <> 0 then HHGear^.Y:= HHGear^.Y + cGravity * 40;
   999 
   994 
  1000 HHGear.Y:= HHGear.Y + cGravity * 100;
   995 HHGear^.Y:= HHGear^.Y + cGravity * 100;
  1001 end;
   996 end;
  1002 
   997 
  1003 ////////////////////////////////////////////////////////////////////////////////
   998 ////////////////////////////////////////////////////////////////////////////////
  1004 const cAirPlaneSpeed = 1.4;
   999 const cAirPlaneSpeed: hwFloat = (isNegative: false; QWordValue: 6012954214); // 1.4
  1005       cBombsDistance = 30;
  1000       cBombsDistance: hwFloat = (isNegative: false; QWordValue: 128849018880); // 30
  1006       cBombsSpeed = 0.1;
  1001       cBombsSpeed   : hwFloat = (isNegative: false; QWordValue:  429496729);
  1007 
  1002 
  1008 procedure doStepAirAttackWork(Gear: PGear);
  1003 procedure doStepAirAttackWork(Gear: PGear);
  1009 begin
  1004 begin
  1010 AllInactive:= false;
  1005 AllInactive:= false;
  1011 Gear.X:= Gear.X + cAirPlaneSpeed;
  1006 Gear^.X:= Gear^.X + cAirPlaneSpeed;
  1012 if (Gear.Health > 0)and(Gear.X >= Gear.dX)and(Gear.X < Gear.dX + cAirPlaneSpeed) then
  1007 if (Gear^.Health > 0)and( not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  1013    begin
  1008    begin
  1014    dec(Gear.Health);
  1009    dec(Gear^.Health);
  1015    case Gear.State of
  1010    case Gear^.State of
  1016         0: AddGear(round(Gear.X), round(Gear.Y), gtAirBomb, 0, cBombsSpeed, 0.0);
  1011         0: AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed, 0, 0);
  1017         1: AddGear(round(Gear.X), round(Gear.Y), gtMine, 0, cBombsSpeed, 0.0);
  1012         1: AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine, 0, cBombsSpeed, 0, 0);
  1018         end;
  1013         end;
  1019    Gear.dX:= Gear.dX + cBombsDistance
  1014    Gear^.dX:= Gear^.dX + cBombsDistance
  1020    end;
  1015    end;
  1021 if Gear.X > 3072 then DeleteGear(Gear)
  1016 if Gear^.X > 3072 then DeleteGear(Gear)
  1022 end;
  1017 end;
  1023 
  1018 
  1024 procedure doStepAirAttack(Gear: PGear);
  1019 procedure doStepAirAttack(Gear: PGear);
  1025 begin
  1020 begin
  1026 AllInactive:= false;
  1021 AllInactive:= false;
  1027 Gear.X:= -1024;
  1022 Gear^.X:= -1024;
  1028 Gear.Y:= -128;
  1023 Gear^.Y:= -128;
  1029 Gear.dX:= TargetPoint.X -
  1024 Gear^.dX:= TargetPoint.X -
  1030           cBombsDistance * 5 / 2 - 
  1025           cBombsDistance * 5 / 2;{ -
  1031           cBombsSpeed * sqrt(2 * (TargetPoint.Y - Gear.Y) / cGravity);
  1026           cBombsSpeed * sqrt(2 * (TargetPoint.Y - Gear^.Y) / cGravity);}
  1032 Gear.Health:= 6;
  1027 Gear^.Health:= 6;
  1033 Gear.doStep:= doStepAirAttackWork
  1028 Gear^.doStep:= @doStepAirAttackWork
  1034 end;
  1029 end;
  1035 
  1030 
  1036 ////////////////////////////////////////////////////////////////////////////////
  1031 ////////////////////////////////////////////////////////////////////////////////
  1037 
  1032 
  1038 procedure doStepAirBomb(Gear: PGear);
  1033 procedure doStepAirBomb(Gear: PGear);
  1039 begin
  1034 begin
  1040 AllInactive:= false;
  1035 AllInactive:= false;
  1041 doStepFallingGear(Gear);
  1036 doStepFallingGear(Gear);
  1042 if (Gear.State and gstCollision) <> 0 then
  1037 if (Gear^.State and gstCollision) <> 0 then
  1043    begin
  1038    begin
  1044    doMakeExplosion(round(Gear.X), round(Gear.Y), 30, EXPLAutoSound);
  1039    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
  1045    DeleteGear(Gear);
  1040    DeleteGear(Gear);
  1046    exit
  1041    exit
  1047    end;
  1042    end;
  1048 if (GameTicks and $3F) = 0 then
  1043 if (GameTicks and $3F) = 0 then
  1049    AddGear(round(Gear.X), round(Gear.Y), gtSmokeTrace, 0)
  1044    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtSmokeTrace, 0, 0, 0, 0)
  1050 end;
  1045 end;
  1051 
       
  1052