hedgewars/HHHandlers.inc
changeset 351 29bc9c36ad5f
parent 304 8096e69e839e
child 369 2aed85310727
equal deleted inserted replaced
350:c3ccec3834e8 351:29bc9c36ad5f
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    17  *)
    17  *)
    18 
    18 
    19 ////////////////////////////////////////////////////////////////////////////////
    19 ////////////////////////////////////////////////////////////////////////////////
    20 procedure Attack(Gear: PGear);
    20 procedure Attack(Gear: PGear);
    21 var xx, yy: Double;
    21 var xx, yy: hwFloat;
    22 begin
    22 begin
    23 with Gear^,
    23 with Gear^,
    24      PHedgehog(Gear.Hedgehog)^ do
    24      PHedgehog(Gear^.Hedgehog)^ do
    25      begin
    25      begin
    26      if ((State and gstHHDriven) <> 0)and
    26      if ((State and gstHHDriven) <> 0)and
    27  //       (((State and gstAttacking) <> 0) or ((Message and gm_Attack) <> 0))and
    27  //       (((State and gstAttacking) <> 0) or ((Message and gm_Attack) <> 0))and
    28         ((State and (gstAttacked or gstMoving or gstHHChooseTarget)) = 0)and
    28         ((State and (gstAttacked or gstMoving or gstHHChooseTarget)) = 0)and
    29         (((State and gstFalling  ) = 0)or((Ammo[CurSlot, CurAmmo].Propz and ammoprop_AttackInFall) <> 0))and
    29         (((State and gstFalling  ) = 0)or((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackInFall) <> 0))and
    30         (((State and gstHHJumping) = 0)or((Ammo[CurSlot, CurAmmo].Propz and ammoprop_AttackInJump) <> 0))and
    30         (((State and gstHHJumping) = 0)or((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackInJump) <> 0))and
    31           ((TargetPoint.X <> NoPointX) or((Ammo[CurSlot, CurAmmo].Propz and ammoprop_NeedTarget) = 0)) then
    31           ((TargetPoint.X <> NoPointX) or((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NeedTarget) = 0)) then
    32         begin
    32         begin
    33         State:= State or gstAttacking;
    33         State:= State or gstAttacking;
    34         if Power = cMaxPower then Message:= Message and not gm_Attack
    34         if Power = cMaxPower then Message:= Message and not gm_Attack
    35         else if (Ammo[CurSlot, CurAmmo].Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
    35         else if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
    36         else begin
    36         else begin
    37              if Power = 0 then
    37              if Power = 0 then
    38                 begin
    38                 begin
    39                 AttackBar:= CurrentTeam.AttackBar;
    39                 AttackBar:= CurrentTeam^.AttackBar;
    40                 PlaySound(sndThrowPowerUp)
    40                 PlaySound(sndThrowPowerUp, false)
    41                 end;
    41                 end;
    42              inc(Power)
    42              inc(Power)
    43              end;
    43              end;
    44         if ((Message and gm_Attack) <> 0) then exit;
    44         if ((Message and gm_Attack) <> 0) then exit;
    45         
    45 
    46         if (Ammo[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0 then
    46         if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0 then
    47            begin
    47            begin
    48            StopSound(sndThrowPowerUp);
    48            StopSound(sndThrowPowerUp);
    49            PlaySound(sndThrowRelease);
    49            PlaySound(sndThrowRelease, false);
    50            end;
    50            end;
    51         xx:= hwSign(dX)*Sin(Angle*pi/cMaxAngle);
    51 //        xx:= hwSign(dX)*Sin(Angle*pi/cMaxAngle);
    52         yy:= -Cos(Angle*pi/cMaxAngle);
    52 //        yy:= -Cos(Angle*pi/cMaxAngle);
    53              case Ammo[CurSlot, CurAmmo].AmmoType of
    53         xx:= AngleSin(Angle);
    54                       amGrenade: FollowGear:= AddGear(round(X), round(Y), gtAmmo_Bomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo[CurSlot, CurAmmo].Timer);
    54         xx.isNegative:= dX.isNegative;
    55                   amClusterBomb: FollowGear:= AddGear(round(X), round(Y), gtClusterBomb,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo[CurSlot, CurAmmo].Timer);
    55         yy:= -AngleCos(Angle);
    56                       amBazooka: FollowGear:= AddGear(round(X), round(Y), gtAmmo_Grenade, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor);
    56              case Ammo^[CurSlot, CurAmmo].AmmoType of
    57                           amUFO: FollowGear:= AddGear(round(X), round(Y), gtUFO,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor);
    57                       amGrenade: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtAmmo_Bomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
       
    58                   amClusterBomb: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtClusterBomb,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
       
    59                       amBazooka: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtAmmo_Grenade, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
       
    60                           amUFO: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtUFO,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
    58                       amShotgun: begin
    61                       amShotgun: begin
    59                                  PlaySound(sndShotgunReload);
    62                                  PlaySound(sndShotgunReload, false);
    60                                  CurAmmoGear:= AddGear(round(X), round(Y), gtShotgunShot,  0, xx * 0.5, yy * 0.5);
    63                                  CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
    61                                  end;
    64                                  end;
    62                    amPickHammer: CurAmmoGear:= AddGear(round(Gear.X), round(Gear.Y) + cHHRadius, gtPickHammer, 0);
    65                    amPickHammer: CurAmmoGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + cHHRadius, gtPickHammer, 0, 0, 0, 0);
    63                          amSkip: TurnTimeLeft:= 0;
    66                          amSkip: TurnTimeLeft:= 0;
    64                          amRope: CurAmmoGear:= AddGear(round(Gear.X), round(Gear.Y), gtRope, 0, xx, yy);
    67                          amRope: CurAmmoGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtRope, 0, xx, yy, 0);
    65                          amMine: AddGear(round(X) + hwSign(dX) * 7, round(Y), gtMine, 0, hwSign(dX) * 0.02, 0, 3000);
    68                          amMine: AddGear(hwRound(X) + hwSign(dX) * 7, hwRound(Y), gtMine, 0, hwSign(dX) * _0_02, 0, 3000);
    66                        amDEagle: AddGear(round(X), round(Y), gtDEagleShot, 0, xx * 0.5, yy * 0.5);
    69                        amDEagle: AddGear(hwRound(X), hwRound(Y), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
    67                      amDynamite: AddGear(round(X) + hwSign(dX) * 7, round(Y), gtDynamite, 0, hwSign(dX) * 0.035, 0, 5000);
    70                      amDynamite: AddGear(hwRound(X) + hwSign(dX) * 7, hwRound(Y), gtDynamite, 0, hwSign(dX) * _0_03, 0, 5000);
    68                   amBaseballBat: AddGear(round(X) + hwSign(dX) * 10, round(Y), gtShover, 0, xx * 0.5, yy * 0.5).Radius:= 20;
    71                   amBaseballBat: AddGear(hwRound(X) + hwSign(dX) * 10, hwRound(Y), gtShover, 0, xx * _0_5, yy * _0_5, 0)^.Radius:= 20;
    69                     amFirePunch: CurAmmoGear:= AddGear(round(X) + hwSign(dX) * 10, round(Y), gtFirePunch, 0);
    72                     amFirePunch: CurAmmoGear:= AddGear(hwRound(X) + hwSign(dX) * 10, hwRound(Y), gtFirePunch, 0, 0, 0, 0);
    70                     amParachute: CurAmmoGear:= AddGear(round(X), round(Y), gtParachute, 0);
    73                     amParachute: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtParachute, 0, 0, 0, 0);
    71                     amAirAttack: AddGear(0, 0, gtAirAttack, 0);
    74                     amAirAttack: AddGear(0, 0, gtAirAttack, 0, 0, 0, 0);
    72                    amMineStrike: AddGear(0, 0, gtAirAttack, 1);
    75                    amMineStrike: AddGear(0, 0, gtAirAttack, 1, 0, 0, 0);
    73                     amBlowTorch: CurAmmoGear:= AddGear(round(Gear.X), round(Gear.Y), gtBlowTorch, 0, hwSign(Gear.dX) * 0.5);
    76                     amBlowTorch: CurAmmoGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtBlowTorch, 0, hwSign(Gear^.dX) * _0_5, 0, 0);
    74                   end;
    77                   end;
    75         Power:= 0;
    78         Power:= 0;
    76         if CurAmmoGear <> nil then
    79         if CurAmmoGear <> nil then
    77            begin
    80            begin
    78            Message:= Message or gm_Attack;
    81            Message:= Message or gm_Attack;
    79            CurAmmoGear.Message:= Message
    82            CurAmmoGear^.Message:= Message
    80            end else begin
    83            end else begin
    81            if not CurrentTeam.ExtDriven and
    84            if not CurrentTeam^.ExtDriven and
    82              ((Ammo[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0) then SendIPC('a');
    85              ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0) then SendIPC('a');
    83            AfterAttack
    86            AfterAttack
    84            end
    87            end
    85         end else Message:= Message and not gm_Attack
    88         end else Message:= Message and not gm_Attack
    86      end
    89      end
    87 end;
    90 end;
    88 
    91 
    89 procedure AfterAttack;
    92 procedure AfterAttack;
    90 begin
    93 begin
    91 with CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog].Gear^,
    94 with CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^,
    92      CurrentTeam.Hedgehogs[CurrentTeam.CurrHedgehog] do
    95      CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog] do
    93      begin
    96      begin
    94         Inc(AttacksNum);
    97         Inc(AttacksNum);
    95         State:= State and not gstAttacking;
    98         State:= State and not gstAttacking;
    96         if Ammo[CurSlot, CurAmmo].NumPerTurn >= AttacksNum then isInMultiShoot:= true
    99         if Ammo^[CurSlot, CurAmmo].NumPerTurn >= AttacksNum then isInMultiShoot:= true
    97            else begin
   100            else begin
    98            TurnTimeLeft:= Ammoz[Ammo[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
   101            TurnTimeLeft:= Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
    99            State:= State or gstAttacked;
   102            State:= State or gstAttacked;
   100            OnUsedAmmo(Ammo)
   103            OnUsedAmmo(Ammo)
   101            end;
   104            end;
   102      AttackBar:= 0;
   105      AttackBar:= 0;
   103      end
   106      end
   106 ////////////////////////////////////////////////////////////////////////////////
   109 ////////////////////////////////////////////////////////////////////////////////
   107 procedure PickUp(HH, Gear: PGear);
   110 procedure PickUp(HH, Gear: PGear);
   108 var s: shortstring;
   111 var s: shortstring;
   109     a: TAmmoType;
   112     a: TAmmoType;
   110 begin
   113 begin
   111 Gear.Message:= gm_Destroy;
   114 Gear^.Message:= gm_Destroy;
   112 case Gear.Pos of
   115 case Gear^.Pos of
   113        posCaseAmmo: begin
   116        posCaseAmmo: begin
   114                     a:= TAmmoType(Gear.State);
   117                     a:= TAmmoType(Gear^.State);
   115                     AddAmmo(PHedgehog(HH.Hedgehog), a);
   118                     AddAmmo(PHedgehog(HH^.Hedgehog), a);
   116                     s:= trammo[Ammoz[a].NameId];
   119                     s:= trammo[Ammoz[a].NameId];
   117                     AddCaption(s, PHedgehog(HH.Hedgehog).Team.Color, capgrpAmmoinfo);
   120                     AddCaption(s, PHedgehog(HH^.Hedgehog)^.Team^.Color, capgrpAmmoinfo);
   118                     end;
   121                     end;
   119      posCaseHealth: begin
   122      posCaseHealth: begin
   120                     inc(HH.Health, Gear.Health);
   123                     inc(HH^.Health, Gear^.Health);
   121                     str(Gear.Health, s);
   124                     str(Gear^.Health, s);
   122                     s:= '+' + s;
   125                     s:= '+' + s;
   123                     AddCaption(s, PHedgehog(HH.Hedgehog).Team.Color, capgrpAmmoinfo);
   126                     AddCaption(s, PHedgehog(HH^.Hedgehog)^.Team^.Color, capgrpAmmoinfo);
   124                     RenderHealth(PHedgehog(HH.Hedgehog)^);
   127                     RenderHealth(PHedgehog(HH^.Hedgehog)^);
   125                     RecountTeamHealth(PHedgehog(HH.Hedgehog)^.Team)
   128                     RecountTeamHealth(PHedgehog(HH^.Hedgehog)^.Team)
   126                     end;
   129                     end;
   127      end;
   130      end;
   128 end;
   131 end;
   129 
   132 
   130 const StepTicks: LongWord = 0;
   133 const StepTicks: LongWord = 0;
   131 
   134 
   132 procedure HedgehogStep(Gear: PGear);
   135 procedure HedgehogStep(Gear: PGear);
   133 var PrevdX: integer;
   136 var PrevdX: integer;
   134 begin
   137 begin
   135 if ((Gear.State and (gstAttacking or gstMoving or gstFalling)) = 0) then
   138 if ((Gear^.State and (gstAttacking or gstMoving or gstFalling)) = 0) then
   136    begin
   139    begin
   137    if ((Gear.Message and gm_LJump ) <> 0) then
   140    if ((Gear^.Message and gm_LJump ) <> 0) then
   138       begin
   141       begin
   139       Gear.Message:= 0;
   142       Gear^.Message:= 0;
   140       if not TestCollisionYwithGear(Gear, -1) then
   143       if not TestCollisionYwithGear(Gear, -1) then
   141          if not TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear.dX)) then Gear.Y:= Gear.Y - 2 else
   144          if not TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - 2 else
   142          if not TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear.dX)) then Gear.Y:= Gear.Y - 1;
   145          if not TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear^.dX)) then Gear^.Y:= Gear^.Y - 1;
   143       if not (TestCollisionXwithGear(Gear, hwSign(Gear.dX))
   146       if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
   144          or   TestCollisionYwithGear(Gear, -1)) then
   147          or   TestCollisionYwithGear(Gear, -1)) then
   145          begin
   148          begin
   146          Gear.dY:= -0.15;
   149          Gear^.dY:= -_0_15;
   147          Gear.dX:= hwSign(Gear.dX) * 0.15;
   150          Gear^.dX:= hwSign(Gear^.dX) * _0_15;
   148          Gear.State:= Gear.State or gstFalling or gstHHJumping;
   151          Gear^.State:= Gear^.State or gstFalling or gstHHJumping;
   149          exit
   152          exit
   150          end;
   153          end;
   151       end;
   154       end;
   152    if ((Gear.Message and gm_HJump ) <> 0) then
   155    if ((Gear^.Message and gm_HJump ) <> 0) then
   153       begin
   156       begin
   154       Gear.Message:= 0;
   157       Gear^.Message:= 0;
   155       if not TestCollisionYwithGear(Gear, -1) then
   158       if not TestCollisionYwithGear(Gear, -1) then
   156          begin
   159          begin
   157          Gear.dY:= -0.20;
   160          Gear^.dY:= -_0_2;
   158          Gear.dX:= 0.0000001 * hwSign(Gear.dX);
   161          SetLittle(Gear^.dX);
   159          Gear.X:= Gear.X - hwSign(Gear.dX)*0.00008; // shift compensation
   162          Gear^.State:= Gear^.State or gstFalling or gstHHJumping;
   160          Gear.State:= Gear.State or gstFalling or gstHHJumping;
       
   161          exit
   163          exit
   162          end;
   164          end;
   163       end;
   165       end;
   164    PrevdX:= hwSign(Gear.dX);
   166    PrevdX:= hwSign(Gear^.dX);
   165    if (Gear.Message and gm_Left  )<>0 then Gear.dX:= -cLittle else
   167    if (Gear^.Message and gm_Left  )<>0 then Gear^.dX:= -cLittle else
   166    if (Gear.Message and gm_Right )<>0 then Gear.dX:=  cLittle else exit;
   168    if (Gear^.Message and gm_Right )<>0 then Gear^.dX:=  cLittle else exit;
   167    StepTicks:= cHHStepTicks;
   169    StepTicks:= cHHStepTicks;
   168    if PrevdX <> hwSign(Gear.dX) then exit;
   170    if PrevdX <> hwSign(Gear^.dX) then exit;
   169    PHedgehog(Gear.Hedgehog).visStepPos:= (PHedgehog(Gear.Hedgehog).visStepPos + 1) and 7;
   171    PHedgehog(Gear^.Hedgehog)^.visStepPos:= (PHedgehog(Gear^.Hedgehog)^.visStepPos + 1) and 7;
   170    if TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then
   172    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   171       begin
   173       begin
   172       if not (TestCollisionXwithXYShift(Gear, 0, -6, hwSign(Gear.dX))
   174       if not (TestCollisionXwithXYShift(Gear, 0, -6, hwSign(Gear^.dX))
   173          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   175          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   174       if not (TestCollisionXwithXYShift(Gear, 0, -5, hwSign(Gear.dX))
   176       if not (TestCollisionXwithXYShift(Gear, 0, -5, hwSign(Gear^.dX))
   175          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   177          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   176       if not (TestCollisionXwithXYShift(Gear, 0, -4, hwSign(Gear.dX))
   178       if not (TestCollisionXwithXYShift(Gear, 0, -4, hwSign(Gear^.dX))
   177          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   179          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   178       if not (TestCollisionXwithXYShift(Gear, 0, -3, hwSign(Gear.dX))
   180       if not (TestCollisionXwithXYShift(Gear, 0, -3, hwSign(Gear^.dX))
   179          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   181          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   180       if not (TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear.dX))
   182       if not (TestCollisionXwithXYShift(Gear, 0, -2, hwSign(Gear^.dX))
   181          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   183          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   182       if not (TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear.dX))
   184       if not (TestCollisionXwithXYShift(Gear, 0, -1, hwSign(Gear^.dX))
   183          or TestCollisionYwithGear(Gear, -1)) then Gear.Y:= Gear.Y - 1;
   185          or TestCollisionYwithGear(Gear, -1)) then Gear^.Y:= Gear^.Y - 1;
   184       end;
   186       end;
   185    if not TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then Gear.X:= Gear.X + hwSign(Gear.dX);
   187    if not TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then Gear^.X:= Gear^.X + hwSign(Gear^.dX);
   186 
   188 
   187    SetAllHHToActive;
   189    SetAllHHToActive;
   188 
   190 
   189    if not TestCollisionYwithGear(Gear, 1) then
   191    if not TestCollisionYwithGear(Gear, 1) then
   190    begin
   192    begin
   191    Gear.Y:= Gear.Y + 1;
   193    Gear^.Y:= Gear^.Y + 1;
   192    if not TestCollisionYwithGear(Gear, 1) then
   194    if not TestCollisionYwithGear(Gear, 1) then
   193    begin
   195    begin
   194    Gear.Y:= Gear.Y + 1;
   196    Gear^.Y:= Gear^.Y + 1;
   195    if not TestCollisionYwithGear(Gear, 1) then
   197    if not TestCollisionYwithGear(Gear, 1) then
   196    begin
   198    begin
   197    Gear.Y:= Gear.Y + 1;
   199    Gear^.Y:= Gear^.Y + 1;
   198    if not TestCollisionYwithGear(Gear, 1) then
   200    if not TestCollisionYwithGear(Gear, 1) then
   199    begin
   201    begin
   200    Gear.Y:= Gear.Y + 1;
   202    Gear^.Y:= Gear^.Y + 1;
   201    if not TestCollisionYwithGear(Gear, 1) then
   203    if not TestCollisionYwithGear(Gear, 1) then
   202    begin
   204    begin
   203    Gear.Y:= Gear.Y + 1;
   205    Gear^.Y:= Gear^.Y + 1;
   204    if not TestCollisionYwithGear(Gear, 1) then
   206    if not TestCollisionYwithGear(Gear, 1) then
   205    begin
   207    begin
   206    Gear.Y:= Gear.Y + 1;
   208    Gear^.Y:= Gear^.Y + 1;
   207    if not TestCollisionYwithGear(Gear, 1) then
   209    if not TestCollisionYwithGear(Gear, 1) then
   208       begin
   210       begin
   209       Gear.Y:= Gear.Y - 6;
   211       Gear^.Y:= Gear^.Y - 6;
   210       Gear.dY:= 0;
   212       Gear^.dY:= 0;
   211       Gear.State:= Gear.State or gstFalling
   213       Gear^.State:= Gear^.State or gstFalling
   212       end;
   214       end;
   213    end
   215    end
   214    end
   216    end
   215    end
   217    end
   216    end
   218    end
   219    end
   221    end
   220 end;
   222 end;
   221 
   223 
   222 procedure HedgehogChAngle(Gear: PGear);
   224 procedure HedgehogChAngle(Gear: PGear);
   223 begin
   225 begin
   224 if ((Gear.State and (gstMoving or gstFalling)) = 0) then
   226 if ((Gear^.State and (gstMoving or gstFalling)) = 0) then
   225    if (Gear.Message and gm_Up    )<>0 then if Gear.Angle > CurMinAngle then dec(Gear.Angle)
   227    if (Gear^.Message and gm_Up    )<>0 then if Gear^.Angle > CurMinAngle then dec(Gear^.Angle)
   226    else else
   228    else else
   227    if (Gear.Message and gm_Down  )<>0 then if Gear.Angle < CurMaxAngle then inc(Gear.Angle);
   229    if (Gear^.Message and gm_Down  )<>0 then if Gear^.Angle < CurMaxAngle then inc(Gear^.Angle);
   228 end;
   230 end;
   229 
   231 
   230 procedure doStepHedgehog(Gear: PGear); forward;
   232 procedure doStepHedgehog(Gear: PGear); forward;
   231 ////////////////////////////////////////////////////////////////////////////////
   233 ////////////////////////////////////////////////////////////////////////////////
   232 procedure doStepHedgehogDriven(Gear: PGear);
   234 procedure doStepHedgehogDriven(Gear: PGear);
   233 var t: PGear;
   235 var t: PGear;
   234 begin
   236 begin
   235 if isInMultiShoot and (Gear.Damage = 0) then
   237 if isInMultiShoot and (Gear^.Damage = 0) then
   236    begin
   238    begin
   237    exit
   239    exit
   238    end;
   240    end;
   239 AllInactive:= false;
   241 AllInactive:= false;
   240 DeleteCI(Gear);
   242 DeleteCI(Gear);
   241 if (TurnTimeLeft = 0) or (Gear.Damage > 0) then
   243 if (TurnTimeLeft = 0) or (Gear^.Damage > 0) then
   242    begin
   244    begin
   243    TurnTimeLeft:= 0;
   245    TurnTimeLeft:= 0;
   244    Gear.State:= Gear.State and not gstHHDriven;
   246    Gear^.State:= Gear^.State and not gstHHDriven;
   245    if Gear.Damage > 0 then
   247    if Gear^.Damage > 0 then
   246       Gear.State:= Gear.State and not gstHHJumping;
   248       Gear^.State:= Gear^.State and not gstHHJumping;
   247    exit
   249    exit
   248    end;
   250    end;
   249 if ((Gear.State and gstFalling) <> 0) or (StepTicks = cHHStepTicks)
   251 if ((Gear^.State and gstFalling) <> 0) or (StepTicks = cHHStepTicks)
   250    or (CurAmmoGear <> nil) then // we're moving
   252    or (CurAmmoGear <> nil) then // we're moving
   251    begin
   253    begin
   252    // check for case with ammo
   254    // check for case with ammo
   253    t:= CheckGearNear(Gear, gtCase, 36, 36);
   255    t:= CheckGearNear(Gear, gtCase, 36, 36);
   254    if t <> nil then
   256    if t <> nil then
   255       PickUp(Gear, t)
   257       PickUp(Gear, t)
   256    end;
   258    end;
   257 
   259 
   258 if CurAmmoGear <> nil then
   260 if CurAmmoGear <> nil then
   259    begin
   261    begin
   260    CurAmmoGear.Message:= Gear.Message;
   262    CurAmmoGear^.Message:= Gear^.Message;
   261    exit
   263    exit
   262    end;
   264    end;
   263 
   265 
   264 if ((Gear.Message and gm_Attack) <> 0) or
   266 if ((Gear^.Message and gm_Attack) <> 0) or
   265    ((Gear.State and gstAttacking) <> 0)then Attack(Gear);
   267    ((Gear^.State and gstAttacking) <> 0)then Attack(Gear);
   266 
   268 
   267 if (Gear.State and gstFalling) <> 0 then
   269 if (Gear^.State and gstFalling) <> 0 then
   268    begin
   270    begin
   269    // it could be the source to trick: double-backspace jump -> vertical wall
   271    // it could be the source to trick: hwFloat-backspace jump -> vertical wall
   270    // collision - > (abs(Gear.dX) < 0.0000002) -> backspace -> even more high jump
   272    // collision - > (abs(Gear^.dX) < 0.0000002) -> backspace -> even more high jump
   271    if ((Gear.Message and gm_HJump) <> 0) and ((Gear.State and gstHHJumping) <> 0) then
   273    if ((Gear^.Message and gm_HJump) <> 0) and ((Gear^.State and gstHHJumping) <> 0) then
   272       if (abs(Gear.dX) < 2 * cLittle) and (Gear.dY < -0.02) then
   274       if (hwAbs(Gear^.dX) < cLittle + cLittle) and (Gear^.dY < -_0_02) then
   273          begin
   275          begin
   274          Gear.dY:= -0.25;
   276          Gear^.dY:= -_0_25;
   275          Gear.dX:= hwSign(Gear.dX) * 0.02
   277          Gear^.dX:= hwSign(Gear^.dX) * _0_02
   276          end;
   278          end;
   277    Gear.Message:= Gear.Message and not (gm_LJump or gm_HJump);     
   279    Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
   278    if TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then SetLittle(Gear.dX);
   280    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then SetLittle(Gear^.dX);
   279    Gear.X:= Gear.X + Gear.dX;
   281    Gear^.X:= Gear^.X + Gear^.dX;
   280    Gear.dY:= Gear.dY + cGravity;
   282    Gear^.dY:= Gear^.dY + cGravity;
   281    if (Gear.dY < 0)and TestCollisionYwithGear(Gear, -1) then Gear.dY:= 0;
   283    if (Gear^.dY < 0)and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= 0;
   282    Gear.Y:= Gear.Y + Gear.dY;
   284    Gear^.Y:= Gear^.Y + Gear^.dY;
   283    if (Gear.dY >= 0)and TestCollisionYwithGear(Gear, 1) then
   285    if (not Gear^.dY.isNegative)and TestCollisionYwithGear(Gear, 1) then
   284       begin
   286       begin
   285       CheckHHDamage(Gear);
   287       CheckHHDamage(Gear);
   286       if ((abs(Gear.dX) + abs(Gear.dY)) < 0.55)
   288       if ((hwAbs(Gear^.dX) + hwAbs(Gear^.dY)) < _0_55)
   287          and ((Gear.State and gstHHJumping) <> 0) then SetLittle(Gear.dX);
   289          and ((Gear^.State and gstHHJumping) <> 0) then SetLittle(Gear^.dX);
   288       Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
   290       Gear^.State:= Gear^.State and not (gstFalling or gstHHJumping);
   289       StepTicks:= 300; 
   291       StepTicks:= 300;
   290       Gear.dY:= 0
   292       Gear^.dY:= 0
   291       end;
   293       end;
   292    CheckGearDrowning(Gear);
   294    CheckGearDrowning(Gear);
   293    exit
   295    exit
   294    end ;//else if Gear.CollIndex = High(Longword) then AddIntersectorsCR(Gear);
   296    end ;//else if Gear^.CollIndex = High(Longword) then AddIntersectorsCR(Gear);
   295 
   297 
   296    HedgehogChAngle(Gear);
   298    HedgehogChAngle(Gear);
   297    if StepTicks > 0 then dec(StepTicks);
   299    if StepTicks > 0 then dec(StepTicks);
   298    if (StepTicks = 0) then HedgehogStep(Gear)
   300    if (StepTicks = 0) then HedgehogStep(Gear)
   299 end;
   301 end;
   302 procedure doStepHedgehogFree(Gear: PGear);
   304 procedure doStepHedgehogFree(Gear: PGear);
   303 begin
   305 begin
   304 //DeleteCI(Gear);
   306 //DeleteCI(Gear);
   305 if not TestCollisionYwithGear(Gear, 1) then
   307 if not TestCollisionYwithGear(Gear, 1) then
   306    begin
   308    begin
   307    if (Gear.dY < 0) and TestCollisionYwithGear(Gear, -1) then Gear.dY:= 0;
   309    if (Gear^.dY < 0) and TestCollisionYwithGear(Gear, -1) then Gear^.dY:= 0;
   308    Gear.State:= Gear.State or gstFalling or gstMoving;
   310    Gear^.State:= Gear^.State or gstFalling or gstMoving;
   309    Gear.dY:= Gear.dY + cGravity
   311    Gear^.dY:= Gear^.dY + cGravity
   310    end else begin
   312    end else begin
   311    CheckHHDamage(Gear);
   313    CheckHHDamage(Gear);
   312    if ((abs(Gear.dX) + abs(Gear.dY)) < 0.55)
   314    if ((hwAbs(Gear^.dX) + hwAbs(Gear^.dY)) < _0_55)
   313       and ((Gear.State and gstHHJumping) <> 0) then SetLittle(Gear.dX);
   315       and ((Gear^.State and gstHHJumping) <> 0) then SetLittle(Gear^.dX);
   314    Gear.State:= Gear.State and not (gstFalling or gstHHJumping);
   316    Gear^.State:= Gear^.State and not (gstFalling or gstHHJumping);
   315    if Gear.dY > 0 then Gear.dY:= 0;
   317    if Gear^.dY > 0 then Gear^.dY:= 0;
   316    if ((Gear.State and gstMoving) <> 0) then Gear.dX:= Gear.dX * Gear.Friction
   318    if ((Gear^.State and gstMoving) <> 0) then Gear^.dX:= Gear^.dX * Gear^.Friction
   317    end;
   319    end;
   318 
   320 
   319 if (Gear.State <> 0) then DeleteCI(Gear);
   321 if (Gear^.State <> 0) then DeleteCI(Gear);
   320 
   322 
   321 if (Gear.State and gstMoving) <> 0 then
   323 if (Gear^.State and gstMoving) <> 0 then
   322    if TestCollisionXwithGear(Gear, hwSign(Gear.dX)) then
   324    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
   323       if ((Gear.State and gstFalling) = 0) then
   325       if ((Gear^.State and gstFalling) = 0) then
   324          if abs(Gear.dX) > 0.01 then
   326          if hwAbs(Gear^.dX) > _0_01 then
   325             if not TestCollisionXwithXYShift(Gear, hwSign(Gear.dX) - Gear.dX, -1, hwSign(Gear.dX)) then begin Gear.X:= Gear.X + Gear.dX; Gear.dX:= Gear.dX * 0.96; Gear.Y:= Gear.Y - 1 end else
   327             if not TestCollisionXwithXYShift(Gear, hwSign(Gear^.dX) - Gear^.dX, -1, hwSign(Gear^.dX)) then begin Gear^.X:= Gear^.X + Gear^.dX; Gear^.dX:= Gear^.dX * _0_96; Gear^.Y:= Gear^.Y - 1 end else
   326             if not TestCollisionXwithXYShift(Gear, hwSign(Gear.dX) - Gear.dX, -2, hwSign(Gear.dX)) then begin Gear.X:= Gear.X + Gear.dX; Gear.dX:= Gear.dX * 0.93; Gear.Y:= Gear.Y - 2 end else
   328             if not TestCollisionXwithXYShift(Gear, hwSign(Gear^.dX) - Gear^.dX, -2, hwSign(Gear^.dX)) then begin Gear^.X:= Gear^.X + Gear^.dX; Gear^.dX:= Gear^.dX * _0_93; Gear^.Y:= Gear^.Y - 2 end else
   327             if not TestCollisionXwithXYShift(Gear, hwSign(Gear.dX) - Gear.dX, -3, hwSign(Gear.dX)) then begin Gear.X:= Gear.X + Gear.dX; Gear.dX:= Gear.dX * 0.90; Gear.Y:= Gear.Y - 3 end else
   329             if not TestCollisionXwithXYShift(Gear, hwSign(Gear^.dX) - Gear^.dX, -3, hwSign(Gear^.dX)) then begin Gear^.X:= Gear^.X + Gear^.dX; Gear^.dX:= Gear^.dX * _0_9; Gear^.Y:= Gear^.Y - 3 end else
   328             if not TestCollisionXwithXYShift(Gear, hwSign(Gear.dX) - Gear.dX, -4, hwSign(Gear.dX)) then begin Gear.X:= Gear.X + Gear.dX; Gear.dX:= Gear.dX * 0.87; Gear.Y:= Gear.Y - 4 end else
   330             if not TestCollisionXwithXYShift(Gear, hwSign(Gear^.dX) - Gear^.dX, -4, hwSign(Gear^.dX)) then begin Gear^.X:= Gear^.X + Gear^.dX; Gear^.dX:= Gear^.dX * _0_87; Gear^.Y:= Gear^.Y - 4 end else
   329             if not TestCollisionXwithXYShift(Gear, hwSign(Gear.dX) - Gear.dX, -5, hwSign(Gear.dX)) then begin Gear.X:= Gear.X + Gear.dX; Gear.dX:= Gear.dX * 0.84; Gear.Y:= Gear.Y - 5 end else
   331             if not TestCollisionXwithXYShift(Gear, hwSign(Gear^.dX) - Gear^.dX, -5, hwSign(Gear^.dX)) then begin Gear^.X:= Gear^.X + Gear^.dX; Gear^.dX:= Gear^.dX * _0_84; Gear^.Y:= Gear^.Y - 5 end else
   330             if abs(Gear.dX) > 0.02 then Gear.dX:= -Gear.Elasticity * Gear.dX
   332             if hwAbs(Gear^.dX) > _0_02 then Gear^.dX:= -Gear^.Elasticity * Gear^.dX
   331                                    else begin
   333                                    else begin
   332                                         Gear.State:= Gear.State and not gstMoving;
   334                                         Gear^.State:= Gear^.State and not gstMoving;
   333                                         SetLittle(Gear.dX)
   335                                         SetLittle(Gear^.dX)
   334                                         end
   336                                         end
   335             else begin
   337             else begin
   336                  Gear.State:= Gear.State and not gstMoving;
   338                  Gear^.State:= Gear^.State and not gstMoving;
   337                  SetLittle(Gear.dX)
   339                  SetLittle(Gear^.dX)
   338                  end
   340                  end
   339          else Gear.dX:= -Gear.Elasticity * Gear.dX;
   341          else Gear^.dX:= -Gear^.Elasticity * Gear^.dX;
   340 
   342 
   341 if ((Gear.State and gstFalling) = 0)and
   343 if ((Gear^.State and gstFalling) = 0)and
   342    (sqr(Gear.dX) + sqr(Gear.dY) < 0.0008) then
   344    (hwAbs(Gear^.dX) + hwAbs(Gear^.dY) < _0_03) then
   343    begin
   345    begin
   344    Gear.State:= Gear.State and not gstMoving;
   346    Gear^.State:= Gear^.State and not gstMoving;
   345    SetLittle(Gear.dX);
   347    SetLittle(Gear^.dX);
   346    Gear.dY:= 0
   348    Gear^.dY:= 0
   347    end else Gear.State:= Gear.State or gstMoving;
   349    end else Gear^.State:= Gear^.State or gstMoving;
   348 
   350 
   349 if (Gear.State and gstMoving) <> 0 then
   351 if (Gear^.State and gstMoving) <> 0 then
   350    begin
   352    begin
   351    Gear.X:= Gear.X + Gear.dX;
   353    Gear^.X:= Gear^.X + Gear^.dX;
   352    Gear.Y:= Gear.Y + Gear.dY;
   354    Gear^.Y:= Gear^.Y + Gear^.dY;
   353    if (Gear.dY > 0) and not TestCollisionYwithGear(Gear, 1) and TestCollisionYwithXYShift(Gear, 0, 1, 1) then
   355    if (Gear^.dY > 0) and not TestCollisionYwithGear(Gear, 1) and TestCollisionYwithXYShift(Gear, 0, 1, 1) then
   354       begin
   356       begin
   355       CheckHHDamage(Gear);
   357       CheckHHDamage(Gear);
   356       Gear.dY:= 0;
   358       Gear^.dY:= 0;
   357       Gear.Y:= Gear.Y + 1
   359       Gear^.Y:= Gear^.Y + 1
   358       end;
   360       end;
   359    end else
   361    end else
   360    if Gear.Health = 0 then
   362    if Gear^.Health = 0 then
   361       begin
   363       begin
   362       if AllInactive then
   364       if AllInactive then
   363          begin
   365          begin
   364          doMakeExplosion(round(Gear.X), round(Gear.Y), 30, EXPLAutoSound);
   366          doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, EXPLAutoSound);
   365          AddGear(round(Gear.X), round(Gear.Y), gtGrave, 0).Hedgehog:= Gear.Hedgehog;
   367          AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, 0, 0, 0)^.Hedgehog:= Gear^.Hedgehog;
   366          DeleteGear(Gear);
   368          DeleteGear(Gear);
   367          SetAllToActive
   369          SetAllToActive
   368          end;
   370          end;
   369       AllInactive:= false;  
   371       AllInactive:= false;
   370       exit
   372       exit
   371       end;
   373       end;
   372 
   374 
   373 AllInactive:= false;
   375 AllInactive:= false;
   374 
   376 
   375 if (not CheckGearDrowning(Gear)) and
   377 if (not CheckGearDrowning(Gear)) and
   376    ((Gear.State and gstMoving) = 0) then
   378    ((Gear^.State and gstMoving) = 0) then
   377       begin
   379       begin
   378       Gear.State:= 0;
   380       Gear^.State:= 0;
   379       Gear.Active:= false;
   381       Gear^.Active:= false;
   380       AddGearCI(Gear);
   382       AddGearCI(Gear);
   381       exit
   383       exit
   382       end
   384       end
   383 end;
   385 end;
   384 
   386 
   385 ////////////////////////////////////////////////////////////////////////////////
   387 ////////////////////////////////////////////////////////////////////////////////
   386 procedure doStepHedgehog(Gear: PGear);
   388 procedure doStepHedgehog(Gear: PGear);
   387 begin
   389 begin
   388 if (Gear.Message and gm_Destroy) <> 0 then
   390 if (Gear^.Message and gm_Destroy) <> 0 then
   389    begin
   391    begin
   390    DeleteGear(Gear);
   392    DeleteGear(Gear);
   391    exit
   393    exit
   392    end;
   394    end;
   393 if (Gear.State and gstHHDriven) = 0 then doStepHedgehogFree(Gear)
   395 if (Gear^.State and gstHHDriven) = 0 then doStepHedgehogFree(Gear)
   394                                     else doStepHedgehogDriven(Gear)
   396                                     else doStepHedgehogDriven(Gear)
   395 end;
   397 end;