hedgewars/HHHandlers.inc
changeset 3836 833c0f32e326
parent 3768 39947624dabb
child 3837 47a623d9cdaa
equal deleted inserted replaced
3835:cbee69165c6a 3836:833c0f32e326
    38         2: PlaySound(sndOw3, Hedgehog^.Team^.voicepack);
    38         2: PlaySound(sndOw3, Hedgehog^.Team^.voicepack);
    39         3: PlaySound(sndOw4, Hedgehog^.Team^.voicepack);
    39         3: PlaySound(sndOw4, Hedgehog^.Team^.voicepack);
    40     end
    40     end
    41 end;
    41 end;
    42 
    42 
       
    43 // Shouldn't more of this ammo switching stuff be moved to uAmmos ?
    43 procedure ChangeAmmo(Gear: PGear);
    44 procedure ChangeAmmo(Gear: PGear);
    44 var slot, i: Longword;
    45 var slot, ammoidx, i: Longword;
       
    46     CurWeapon: PAmmo;
    45 begin
    47 begin
    46 slot:= Gear^.MsgParam;
    48 slot:= Gear^.MsgParam;
    47 
    49 
    48 with PHedgehog(Gear^.Hedgehog)^ do
    50 with PHedgehog(Gear^.Hedgehog)^ do
    49     begin
    51     begin
    50     Gear^.Message:= Gear^.Message and not gm_Slot;
    52     Gear^.Message:= Gear^.Message and not gm_Slot;
       
    53     ammoidx:= 0;
       
    54     while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx);
       
    55     CurWeapon:= @Ammo^[slot, ammoidx];
    51 
    56 
    52     if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
    57     if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
    53        ((MultiShootAttacks > 0) and ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) = 0)) or
    58        ((MultiShootAttacks > 0) and ((CurWeapon^.Propz and ammoprop_NoRoundEndHint) = 0)) or
    54        ((Gear^.State and gstHHDriven) = 0) then exit;
    59        ((Gear^.State and gstHHDriven) = 0) then exit;
    55 
    60 
    56     if ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
    61     if ((CurWeapon^.Propz and ammoprop_NoRoundEndHint) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
    57 
    62 
    58     MultiShootAttacks:= 0;
    63     MultiShootAttacks:= 0;
    59     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
    64     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
    60 
    65     
    61     if CurSlot = slot then
    66     if Ammoz[CurAmmoType].Slot = slot then
    62         begin
    67         begin
    63         i:= 0;
    68         i:= 0;
    64         repeat
    69         repeat
    65         inc(CurAmmo);
    70         inc(ammoidx);
    66         if (CurAmmo > cMaxSlotAmmoIndex) then
    71         if (ammoidx > cMaxSlotAmmoIndex) then
    67             begin
    72             begin
    68             CurAmmo:= 0;
    73             ammoidx:= 0;
    69             inc(i);
    74             inc(i);
    70             TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
    75             TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
    71             end;
    76             end;
    72         until (Ammo^[slot, CurAmmo].Count > 0) and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, CurAmmo].AmmoType].SkipTurns)
    77         until (Ammo^[slot, ammoidx].Count > 0) and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns)
    73         end else
    78         end else
    74         begin
    79         begin
    75         i:= 0;
    80         i:= 0;
    76         // check whether there is ammo in slot
    81         // check whether there is ammo in slot
    77         while (i <= cMaxSlotAmmoIndex)
    82         while (i <= cMaxSlotAmmoIndex)
    78           and ((Ammo^[slot, i].Count = 0)
    83           and ((Ammo^[slot, i].Count = 0)
    79                or (Team^.Clan^.TurnNumber <= Ammoz[Ammo^[slot, i].AmmoType].SkipTurns)) do inc(i);
    84                or (Team^.Clan^.TurnNumber <= Ammoz[Ammo^[slot, i].AmmoType].SkipTurns)) do inc(i);
    80 
    85 
    81         if i <= cMaxSlotAmmoIndex then
    86         if i <= cMaxSlotAmmoIndex then ammoidx:= i
    82             begin
    87         end;
    83             CurSlot:= slot;
    88         CurAmmoType:= Ammo^[slot, ammoidx].AmmoType;
    84             CurAmmo:= i
       
    85             end
       
    86         end
       
    87     end
    89     end
    88 end;
    90 end;
    89 
    91 
    90 procedure HHSetWeapon(Gear: PGear);
    92 procedure HHSetWeapon(Gear: PGear);
    91 var t: LongInt;
    93 var t: LongInt;
    92     weap: TAmmoType;
    94     weap: TAmmoType;
       
    95     Hedgehog: PHedgehog;
    93 begin
    96 begin
    94 weap:= TAmmoType(Gear^.MsgParam);
    97 weap:= TAmmoType(Gear^.MsgParam);
    95 
    98 Hedgehog:= PHedgehog(Gear^.Hedgehog);
    96 if PHedgehog(Gear^.Hedgehog)^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
    99 
       
   100 if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
    97 
   101 
    98 Gear^.MsgParam:= Ammoz[weap].Slot;
   102 Gear^.MsgParam:= Ammoz[weap].Slot;
    99 
   103 
   100 t:= cMaxSlotAmmoIndex;
   104 t:= cMaxSlotAmmoIndex;
   101 
   105 
   102 Gear^.Message:= Gear^.Message and not gm_Weapon;
   106 Gear^.Message:= Gear^.Message and not gm_Weapon;
   103 
   107 
   104 with PHedgehog(Gear^.Hedgehog)^ do
   108 with Hedgehog^ do
   105     while (Ammo^[CurSlot, CurAmmo].AmmoType <> weap) and (t >= 0) do
   109     while (CurAmmoType <> weap) and (t >= 0) do
   106         begin
   110         begin
   107         ChangeAmmo(Gear);
   111         ChangeAmmo(Gear);
   108         dec(t)
   112         dec(t)
   109         end;
   113         end;
   110 
   114 
   111 ApplyAmmoChanges(PHedgehog(Gear^.Hedgehog)^)
   115 ApplyAmmoChanges(PHedgehog(Gear^.Hedgehog)^)
   112 end;
   116 end;
   113 
   117 
   114 procedure HHSetTimer(Gear: PGear);
   118 procedure HHSetTimer(Gear: PGear);
       
   119 var CurWeapon: PAmmo;
   115 begin
   120 begin
   116 Gear^.Message:= Gear^.Message and not gm_Timer;
   121 Gear^.Message:= Gear^.Message and not gm_Timer;
       
   122 CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
   117 with PHedgehog(Gear^.Hedgehog)^ do
   123 with PHedgehog(Gear^.Hedgehog)^ do
   118     if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Timerable) <> 0 then
   124     if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
   119         begin
   125         begin
   120         Ammo^[CurSlot, CurAmmo].Timer:= 1000 * Gear^.MsgParam;
   126         CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
   121         with CurrentTeam^ do
   127         with CurrentTeam^ do
   122             ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
   128             ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
   123         end;
   129         end;
   124 end;
   130 end;
   125 
   131 
   126 
   132 
   127 procedure Attack(Gear: PGear);
   133 procedure Attack(Gear: PGear);
   128 var xx, yy, lx, ly: hwFloat;
   134 var xx, yy, lx, ly: hwFloat;
   129     tmpGear: PVisualGear;
   135     tmpGear: PVisualGear;
   130     tmpGear2: PGear;
   136     CurWeapon: PAmmo;
   131 begin
   137 begin
   132 bShowFinger:= false;
   138 bShowFinger:= false;
       
   139 CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
   133 with Gear^,
   140 with Gear^,
   134      PHedgehog(Gear^.Hedgehog)^ do
   141      PHedgehog(Gear^.Hedgehog)^ do
   135      begin
   142      begin
   136      if ((State and gstHHDriven) <> 0)and
   143      if ((State and gstHHDriven) <> 0)and
   137         ((State and (gstAttacked or gstHHChooseTarget)) = 0) and
   144         ((State and (gstAttacked or gstHHChooseTarget)) = 0) and
   138         (((State and gstMoving) = 0) or
   145         (((State and gstMoving) = 0) or
   139             // Allow attacks while moving on ammo with AltAttack
   146             // Allow attacks while moving on ammo with AltAttack
   140             ((CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)) or
   147             ((CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)) or
   141             ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackInMove) <> 0)) and
   148             ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackInMove) <> 0)) and
   142         ((TargetPoint.X <> NoPointX) or ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NeedTarget) = 0)) then
   149         ((TargetPoint.X <> NoPointX) or ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) = 0)) then
   143         begin
   150         begin
   144         State:= State or gstAttacking;
   151         State:= State or gstAttacking;
   145         if Power = cMaxPower then Message:= Message and not gm_Attack
   152         if Power = cMaxPower then Message:= Message and not gm_Attack
   146         else if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
   153         else if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
   147         else begin
   154         else begin
   148              if Power = 0 then
   155              if Power = 0 then
   149                 begin
   156                 begin
   150                 AttackBar:= CurrentTeam^.AttackBar;
   157                 AttackBar:= CurrentTeam^.AttackBar;
   151                 PlaySound(sndThrowPowerUp)
   158                 PlaySound(sndThrowPowerUp)
   152                 end;
   159                 end;
   153              inc(Power)
   160              inc(Power)
   154              end;
   161              end;
   155         if ((Message and gm_Attack) <> 0) then exit;
   162         if ((Message and gm_Attack) <> 0) then exit;
   156 
   163 
   157         if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0 then
   164         if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then
   158            begin
   165            begin
   159            StopSound(sndThrowPowerUp);
   166            StopSound(sndThrowPowerUp);
   160            PlaySound(sndThrowRelease);
   167            PlaySound(sndThrowRelease);
   161            end;
   168            end;
   162 
   169 
   163         xx:= SignAs(AngleSin(Angle), dX);
   170         xx:= SignAs(AngleSin(Angle), dX);
   164         yy:= -AngleCos(Angle);
   171         yy:= -AngleCos(Angle);
   165 
   172 
   166         lx:= X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(dX), Angle)));
   173         lx:= X + int2hwfloat(round(GetLaunchX(CurAmmoType, hwSign(dX), Angle)));
   167         ly:= Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Angle)));
   174         ly:= Y + int2hwfloat(round(GetLaunchY(CurAmmoType, Angle)));
   168 
   175 
   169         if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then xx:= - xx;
   176         if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then xx:= - xx;
   170         if Ammo^[CurSlot, CurAmmo].AttackVoice <> sndNone then
   177         if Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then
   171            PlaySound(Ammo^[CurSlot, CurAmmo].AttackVoice, CurrentTeam^.voicepack);
   178            PlaySound(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack);
   172              case Ammo^[CurSlot, CurAmmo].AmmoType of
   179              case CurAmmoType of
   173                       amGrenade: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Bomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
   180                       amGrenade: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Bomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
   174                       amMolotov: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov,      0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   181                       amMolotov: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov,      0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   175                   amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
   182                   amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
   176                       amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
   183                       amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
   177                       amBazooka: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Grenade, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   184                       amBazooka: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Grenade, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   178                           amBee: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtBee,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   185                           amBee: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtBee,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   179                       amShotgun: begin
   186                       amShotgun: begin
   180                                  PlaySound(sndShotgunReload);
   187                                  PlaySound(sndShotgunReload);
   181                                  CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
   188                                  CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
   205                   amBaseballBat: begin
   212                   amBaseballBat: begin
   206                                  CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
   213                                  CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
   207                                  PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
   214                                  PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
   208                                  end;
   215                                  end;
   209                     amParachute: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
   216                     amParachute: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
   210                     // we save Ammo^[CurSlot, CurAmmo].Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
   217                     // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
   211                     amAirAttack: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 0, _0, _0, 0);
   218                     amAirAttack: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
   212                    amMineStrike: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 1, _0, _0, 0);
   219                    amMineStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
   213                     amBlowTorch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
   220                     amBlowTorch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
   214                        amGirder: CurAmmoGear:= AddGear(0, 0, gtGirder, Ammo^[CurSlot, CurAmmo].Pos, _0, _0, 0);
   221                        amGirder: CurAmmoGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
   215                      amTeleport: CurAmmoGear:= AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtTeleport, 0, _0, _0, 0);
   222                      amTeleport: CurAmmoGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
   216                        amSwitch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
   223                        amSwitch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
   217                        amMortar: begin
   224                        amMortar: begin
   218                                  playSound(sndMortar);
   225                                  playSound(sndMortar);
   219                                  FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtMortar,  0, xx*cMaxPower/cPowerDivisor, yy*cMaxPower/cPowerDivisor, 0);
   226                                  FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtMortar,  0, xx*cMaxPower/cPowerDivisor, yy*cMaxPower/cPowerDivisor, 0);
   220                                  end;
   227                                  end;
   223                                  CurAmmoGear^.SoundChannel:= LoopSound(sndRCPlane, nil)
   230                                  CurAmmoGear^.SoundChannel:= LoopSound(sndRCPlane, nil)
   224                                  end;
   231                                  end;
   225                        amKamikaze: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtKamikaze, 0, xx * _0_5, yy * _0_5, 0);
   232                        amKamikaze: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtKamikaze, 0, xx * _0_5, yy * _0_5, 0);
   226                          amCake: CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 3, hwRound(ly), gtCake, 0, xx, _0, 0);
   233                          amCake: CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 3, hwRound(ly), gtCake, 0, xx, _0, 0);
   227                     amSeduction: CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius * 2), hwRound(ly + yy * cHHRadius * 2), gtSeduction, 0, xx * _0_4, yy * _0_4, 0);
   234                     amSeduction: CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius * 2), hwRound(ly + yy * cHHRadius * 2), gtSeduction, 0, xx * _0_4, yy * _0_4, 0);
   228                    amWatermelon: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
   235                    amWatermelon: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
   229                   amHellishBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtHellishBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   236                   amHellishBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtHellishBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   230                        amNapalm: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 2, _0, _0, 0);
   237                        amNapalm: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
   231                         amDrill: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtDrill, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   238                         amDrill: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtDrill, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
   232                       amBallgun: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun,  0, xx * _0_5, yy * _0_5, 0);
   239                       amBallgun: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun,  0, xx * _0_5, yy * _0_5, 0);
   233                     amJetpack: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtJetpack, 0, _0, _0, 0);
   240                     amJetpack: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtJetpack, 0, _0, _0, 0);
   234                     amBirdy: begin
   241                     amBirdy: begin
   235                              PlaySound(sndWhistle);
   242                              PlaySound(sndWhistle);
   256                                PauseMusic
   263                                PauseMusic
   257                                end;
   264                                end;
   258                       amFlamethrower: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
   265                       amFlamethrower: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
   259                   end;
   266                   end;
   260 
   267 
   261         uStats.AmmoUsed(Ammo^[CurSlot, CurAmmo].AmmoType);
   268         uStats.AmmoUsed(CurAmmoType);
   262 
   269 
   263         if not (SpeechText = '') then
   270         if not (SpeechText = '') then
   264             begin
   271             begin
   265             tmpGear:= AddVisualGear(0, 0, vgtSpeechBubble);
   272             tmpGear:= AddVisualGear(0, 0, vgtSpeechBubble);
   266             if tmpGear <> nil then
   273             if tmpGear <> nil then
   272             SpeechText:= ''
   279             SpeechText:= ''
   273             end;
   280             end;
   274 
   281 
   275         Power:= 0;
   282         Power:= 0;
   276         if (CurAmmoGear <> nil)
   283         if (CurAmmoGear <> nil)
   277            and (((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
   284            and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
   278            begin
   285            begin
   279            CurAmmoGear^.Ammo:= @(Ammo^[CurSlot, CurAmmo]);
   286            CurAmmoGear^.AmmoType:= CurAmmoType;
   280            CurAmmoGear^.AmmoType:= CurAmmoGear^.Ammo^.AmmoType;
       
   281            Message:= Message or gm_Attack;
   287            Message:= Message or gm_Attack;
   282            CurAmmoGear^.Message:= Message
   288            CurAmmoGear^.Message:= Message
   283            end else begin
   289            end else begin
   284            if not CurrentTeam^.ExtDriven and
   290            if not CurrentTeam^.ExtDriven and
   285              ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0) then SendIPC('a');
   291              ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then SendIPC('a');
   286            AfterAttack;
   292            AfterAttack;
   287            end
   293            end
   288         end else Message:= Message and not gm_Attack;
   294         end else Message:= Message and not gm_Attack;
   289      end
   295      end
   290 end;
   296 end;
   294 begin
   300 begin
   295 with CurrentHedgehog^.Gear^,
   301 with CurrentHedgehog^.Gear^,
   296         CurrentHedgehog^ do
   302         CurrentHedgehog^ do
   297     begin
   303     begin
   298     State:= State and not gstAttacking;
   304     State:= State and not gstAttacking;
   299     if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_Effect) = 0 then
   305     if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Effect) = 0 then
   300         begin
   306         begin
   301         Inc(MultiShootAttacks);
   307         Inc(MultiShootAttacks);
   302         
   308         
   303         if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) then
   309         if (Ammoz[CurAmmoType].Ammo.NumPerTurn >= MultiShootAttacks) then
   304             begin
   310             begin
   305             s:= inttostr(Ammo^[CurSlot, CurAmmo].NumPerTurn - MultiShootAttacks + 1);
   311             s:= inttostr(Ammoz[CurAmmoType].Ammo.NumPerTurn - MultiShootAttacks + 1);
   306             AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
   312             AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
   307             end;
   313             end;
   308         
   314         
   309         if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) or
   315         if (Ammoz[CurAmmoType].Ammo.NumPerTurn >= MultiShootAttacks) or
   310             ((GameFlags and gfMultiWeapon) <> 0) then
   316             ((GameFlags and gfMultiWeapon) <> 0) then
   311             begin
   317             begin
   312             isInMultiShoot:= true
   318             isInMultiShoot:= true
   313             end
   319             end
   314         else
   320         else
   315             begin
   321             begin
   316             if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_NoRoundEndHint) = 0 then
   322             if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEndHint) = 0 then
   317                 begin
   323                 begin
   318                 OnUsedAmmo(CurrentHedgehog^);
   324                 OnUsedAmmo(CurrentHedgehog^);
   319                 TurnTimeLeft:= Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
   325                 TurnTimeLeft:= Ammoz[CurAmmoType].TimeAfterTurn;
   320                 State:= State or gstAttacked
   326                 State:= State or gstAttacked
   321                 end
   327                 end
   322             else
   328             else
   323                 begin
   329                 begin
   324                 OnUsedAmmo(CurrentHedgehog^);
   330                 OnUsedAmmo(CurrentHedgehog^);
   329     else
   335     else
   330         begin
   336         begin
   331         OnUsedAmmo(CurrentHedgehog^);
   337         OnUsedAmmo(CurrentHedgehog^);
   332         ApplyAmmoChanges(CurrentHedgehog^);
   338         ApplyAmmoChanges(CurrentHedgehog^);
   333         end;
   339         end;
   334     AttackBar:= 0;
   340     AttackBar:= 0
   335     end
   341     end
   336 end;
   342 end;
   337 
   343 
   338 ////////////////////////////////////////////////////////////////////////////////
   344 ////////////////////////////////////////////////////////////////////////////////
   339 procedure doStepHedgehogDead(Gear: PGear);
   345 procedure doStepHedgehogDead(Gear: PGear);
   447 
   453 
   448 const StepTicks: LongWord = 0;
   454 const StepTicks: LongWord = 0;
   449 
   455 
   450 procedure HedgehogStep(Gear: PGear);
   456 procedure HedgehogStep(Gear: PGear);
   451 var PrevdX: LongInt;
   457 var PrevdX: LongInt;
   452 begin
   458     CurWeapon: PAmmo;
       
   459 begin
       
   460 CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
   453 if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
   461 if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
   454    begin
   462    begin
   455    if isCursorVisible then
   463    if isCursorVisible then
   456       with PHedgehog(Gear^.Hedgehog)^ do
   464       with PHedgehog(Gear^.Hedgehog)^ do
   457         with Ammo^[CurSlot, CurAmmo] do
   465         with CurWeapon^ do
   458           begin
   466           begin
   459           if (Gear^.Message and gm_Left  ) <> 0 then
   467           if (Gear^.Message and gm_Left  ) <> 0 then
   460              Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
   468              Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
   461           else
   469           else
   462           if (Gear^.Message and gm_Right ) <> 0 then
   470           if (Gear^.Message and gm_Right ) <> 0 then
   581 
   589 
   582 procedure HedgehogChAngle(Gear: PGear);
   590 procedure HedgehogChAngle(Gear: PGear);
   583 var da: LongWord;
   591 var da: LongWord;
   584 begin
   592 begin
   585 with PHedgehog(Gear^.Hedgehog)^ do
   593 with PHedgehog(Gear^.Hedgehog)^ do
   586     if (Ammo^[CurSlot, CurAmmo].AmmoType = amRope)
   594     if (CurAmmoType = amRope)
   587     and ((Gear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
   595     and ((Gear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
   588 
   596 
   589 if (((Gear^.Message and gm_Precise) = 0) or ((GameTicks mod 5) = 1)) then
   597 if (((Gear^.Message and gm_Precise) = 0) or ((GameTicks mod 5) = 1)) then
   590     if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Angle >= CurMinAngle + da) then dec(Gear^.Angle, da)
   598     if ((Gear^.Message and gm_Up) <> 0) and (Gear^.Angle >= CurMinAngle + da) then dec(Gear^.Angle, da)
   591     else
   599     else
   700 end;
   708 end;
   701 
   709 
   702 procedure doStepHedgehogDriven(Gear: PGear);
   710 procedure doStepHedgehogDriven(Gear: PGear);
   703 var t: PGear;
   711 var t: PGear;
   704     wasJumping: boolean;
   712     wasJumping: boolean;
   705 begin
   713     Hedgehog: PHedgehog;
       
   714 begin
       
   715 Hedgehog:= PHedgehog(Gear^.Hedgehog);
   706 if not isInMultiShoot then
   716 if not isInMultiShoot then
   707    AllInactive:= false
   717    AllInactive:= false
   708 else
   718 else
   709    Gear^.Message:= 0;
   719    Gear^.Message:= 0;
   710 
   720 
   720     end;
   730     end;
   721 
   731 
   722 if (Gear^.State and gstAnimation) <> 0 then
   732 if (Gear^.State and gstAnimation) <> 0 then
   723     begin
   733     begin
   724     Gear^.Message:= 0;
   734     Gear^.Message:= 0;
   725     if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
   735     if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
   726     inc(Gear^.Timer);
   736     inc(Gear^.Timer);
   727     if Gear^.Timer = Wavez[TWave(Gear^.Tag)].Interval then
   737     if Gear^.Timer = Wavez[TWave(Gear^.Tag)].Interval then
   728         begin
   738         begin
   729         Gear^.Timer:= 0;
   739         Gear^.Timer:= 0;
   730         inc(Gear^.Pos);
   740         inc(Gear^.Pos);
   736 
   746 
   737 if ((Gear^.State and gstMoving) <> 0)
   747 if ((Gear^.State and gstMoving) <> 0)
   738     or (StepTicks = cHHStepTicks)
   748     or (StepTicks = cHHStepTicks)
   739     or (CurAmmoGear <> nil) then // we are moving
   749     or (CurAmmoGear <> nil) then // we are moving
   740     begin
   750     begin
   741     with PHedgehog(Gear^.Hedgehog)^ do
   751     with Hedgehog^ do
   742         if (CurAmmoGear = nil)
   752         if (CurAmmoGear = nil)
   743         and (Gear^.dY > _0_39)
   753         and (Gear^.dY > _0_39)
   744         and (Ammo^[CurSlot, CurAmmo].AmmoType = amParachute) then Gear^.Message:= Gear^.Message or gm_Attack;
   754         and (CurAmmoType = amParachute) then Gear^.Message:= Gear^.Message or gm_Attack;
   745     // check for case with ammo
   755     // check for case with ammo
   746     t:= CheckGearNear(Gear, gtCase, 36, 36);
   756     t:= CheckGearNear(Gear, gtCase, 36, 36);
   747     if t <> nil then
   757     if t <> nil then
   748         PickUp(Gear, t)
   758         PickUp(Gear, t)
   749     end;
   759     end;
   751 if (CurAmmoGear = nil) then
   761 if (CurAmmoGear = nil) then
   752     if (((Gear^.Message and gm_Attack) <> 0)
   762     if (((Gear^.Message and gm_Attack) <> 0)
   753         or ((Gear^.State and gstAttacking) <> 0)) then
   763         or ((Gear^.State and gstAttacking) <> 0)) then
   754         Attack(Gear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
   764         Attack(Gear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
   755     else
   765     else
   756 else with PHedgehog(Gear^.Hedgehog)^ do
   766 else 
   757      if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
   767     with Hedgehog^ do
   758         and ((Gear^.Message and gm_LJump) <> 0)
   768         if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
   759         and (((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_AltUse) <> 0) then
   769             and ((Gear^.Message and gm_LJump) <> 0)
   760         begin
   770             and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
   761         Gear^.Message:= Gear^.Message and not gm_LJump;
   771             begin
   762         Attack(Gear)
   772             Gear^.Message:= Gear^.Message and not gm_LJump;
   763         end;
   773             Attack(Gear)
       
   774             end;
   764 
   775 
   765 if (CurAmmoGear = nil)
   776 if (CurAmmoGear = nil)
   766     or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) then
   777     or ((Ammoz[Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) then
   767     begin
   778     begin
   768     if ((Gear^.Message and gm_Slot) <> 0) then
   779     if ((Gear^.Message and gm_Slot) <> 0) then
   769         begin
   780         begin
   770         ChangeAmmo(Gear);
   781         ChangeAmmo(Gear);
   771         ApplyAmmoChanges(PHedgehog(Gear^.Hedgehog)^)
   782         ApplyAmmoChanges(Hedgehog^)
   772         end;
   783         end;
   773 
   784 
   774     if ((Gear^.Message and gm_Weapon) <> 0) then HHSetWeapon(Gear);
   785     if ((Gear^.Message and gm_Weapon) <> 0) then HHSetWeapon(Gear);
   775 
   786 
   776     if ((Gear^.Message and gm_Timer) <> 0) then HHSetTimer(Gear);
   787     if ((Gear^.Message and gm_Timer) <> 0) then HHSetTimer(Gear);
   795         if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   806         if (not (hwAbs(Gear^.dX) > cLittle)) and (Gear^.dY < -_0_02) then
   796             begin
   807             begin
   797             Gear^.State:= Gear^.State or gstHHHJump;
   808             Gear^.State:= Gear^.State or gstHHHJump;
   798             Gear^.dY:= -_0_25;
   809             Gear^.dY:= -_0_25;
   799             if not cArtillery then Gear^.dX:= -SignAs(_0_02, Gear^.dX);
   810             if not cArtillery then Gear^.dX:= -SignAs(_0_02, Gear^.dX);
   800             PlaySound(sndJump2, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack)
   811             PlaySound(sndJump2, Hedgehog^.Team^.voicepack)
   801             end;
   812             end;
   802 
   813 
   803     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
   814     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
   804 
   815 
   805     if (not cArtillery) and wasJumping and
   816     if (not cArtillery) and wasJumping and