hedgewars/HHHandlers.inc
changeset 3836 833c0f32e326
parent 3768 39947624dabb
child 3837 47a623d9cdaa
--- a/hedgewars/HHHandlers.inc	Mon Sep 06 20:40:58 2010 +0100
+++ b/hedgewars/HHHandlers.inc	Mon Sep 06 16:23:47 2010 -0400
@@ -40,36 +40,41 @@
     end
 end;
 
+// Shouldn't more of this ammo switching stuff be moved to uAmmos ?
 procedure ChangeAmmo(Gear: PGear);
-var slot, i: Longword;
+var slot, ammoidx, i: Longword;
+    CurWeapon: PAmmo;
 begin
 slot:= Gear^.MsgParam;
 
 with PHedgehog(Gear^.Hedgehog)^ do
     begin
     Gear^.Message:= Gear^.Message and not gm_Slot;
+    ammoidx:= 0;
+    while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx);
+    CurWeapon:= @Ammo^[slot, ammoidx];
 
     if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
-       ((MultiShootAttacks > 0) and ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) = 0)) or
+       ((MultiShootAttacks > 0) and ((CurWeapon^.Propz and ammoprop_NoRoundEndHint) = 0)) or
        ((Gear^.State and gstHHDriven) = 0) then exit;
 
-    if ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
+    if ((CurWeapon^.Propz and ammoprop_NoRoundEndHint) <> 0) and (MultiShootAttacks > 0) then OnUsedAmmo(PHedgehog(Gear^.Hedgehog)^);
 
     MultiShootAttacks:= 0;
     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
-
-    if CurSlot = slot then
+    
+    if Ammoz[CurAmmoType].Slot = slot then
         begin
         i:= 0;
         repeat
-        inc(CurAmmo);
-        if (CurAmmo > cMaxSlotAmmoIndex) then
+        inc(ammoidx);
+        if (ammoidx > cMaxSlotAmmoIndex) then
             begin
-            CurAmmo:= 0;
+            ammoidx:= 0;
             inc(i);
             TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
             end;
-        until (Ammo^[slot, CurAmmo].Count > 0) and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, CurAmmo].AmmoType].SkipTurns)
+        until (Ammo^[slot, ammoidx].Count > 0) and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns)
         end else
         begin
         i:= 0;
@@ -78,22 +83,21 @@
           and ((Ammo^[slot, i].Count = 0)
                or (Team^.Clan^.TurnNumber <= Ammoz[Ammo^[slot, i].AmmoType].SkipTurns)) do inc(i);
 
-        if i <= cMaxSlotAmmoIndex then
-            begin
-            CurSlot:= slot;
-            CurAmmo:= i
-            end
-        end
+        if i <= cMaxSlotAmmoIndex then ammoidx:= i
+        end;
+        CurAmmoType:= Ammo^[slot, ammoidx].AmmoType;
     end
 end;
 
 procedure HHSetWeapon(Gear: PGear);
 var t: LongInt;
     weap: TAmmoType;
+    Hedgehog: PHedgehog;
 begin
 weap:= TAmmoType(Gear^.MsgParam);
+Hedgehog:= PHedgehog(Gear^.Hedgehog);
 
-if PHedgehog(Gear^.Hedgehog)^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
+if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then exit; // weapon is not activated yet
 
 Gear^.MsgParam:= Ammoz[weap].Slot;
 
@@ -101,8 +105,8 @@
 
 Gear^.Message:= Gear^.Message and not gm_Weapon;
 
-with PHedgehog(Gear^.Hedgehog)^ do
-    while (Ammo^[CurSlot, CurAmmo].AmmoType <> weap) and (t >= 0) do
+with Hedgehog^ do
+    while (CurAmmoType <> weap) and (t >= 0) do
         begin
         ChangeAmmo(Gear);
         dec(t)
@@ -112,12 +116,14 @@
 end;
 
 procedure HHSetTimer(Gear: PGear);
+var CurWeapon: PAmmo;
 begin
 Gear^.Message:= Gear^.Message and not gm_Timer;
+CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
 with PHedgehog(Gear^.Hedgehog)^ do
-    if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Timerable) <> 0 then
+    if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
         begin
-        Ammo^[CurSlot, CurAmmo].Timer:= 1000 * Gear^.MsgParam;
+        CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
         with CurrentTeam^ do
             ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
         end;
@@ -127,9 +133,10 @@
 procedure Attack(Gear: PGear);
 var xx, yy, lx, ly: hwFloat;
     tmpGear: PVisualGear;
-    tmpGear2: PGear;
+    CurWeapon: PAmmo;
 begin
 bShowFinger:= false;
+CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
 with Gear^,
      PHedgehog(Gear^.Hedgehog)^ do
      begin
@@ -138,12 +145,12 @@
         (((State and gstMoving) = 0) or
             // Allow attacks while moving on ammo with AltAttack
             ((CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)) or
-            ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_AttackInMove) <> 0)) and
-        ((TargetPoint.X <> NoPointX) or ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NeedTarget) = 0)) then
+            ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AttackInMove) <> 0)) and
+        ((TargetPoint.X <> NoPointX) or ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) = 0)) then
         begin
         State:= State or gstAttacking;
         if Power = cMaxPower then Message:= Message and not gm_Attack
-        else if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
+        else if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0 then Message:= Message and not gm_Attack
         else begin
              if Power = 0 then
                 begin
@@ -154,7 +161,7 @@
              end;
         if ((Message and gm_Attack) <> 0) then exit;
 
-        if (Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0 then
+        if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then
            begin
            StopSound(sndThrowPowerUp);
            PlaySound(sndThrowRelease);
@@ -163,17 +170,17 @@
         xx:= SignAs(AngleSin(Angle), dX);
         yy:= -AngleCos(Angle);
 
-        lx:= X + int2hwfloat(round(GetLaunchX(Ammo^[CurSlot, CurAmmo].AmmoType, hwSign(dX), Angle)));
-        ly:= Y + int2hwfloat(round(GetLaunchY(Ammo^[CurSlot, CurAmmo].AmmoType, Angle)));
+        lx:= X + int2hwfloat(round(GetLaunchX(CurAmmoType, hwSign(dX), Angle)));
+        ly:= Y + int2hwfloat(round(GetLaunchY(CurAmmoType, Angle)));
 
         if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then xx:= - xx;
-        if Ammo^[CurSlot, CurAmmo].AttackVoice <> sndNone then
-           PlaySound(Ammo^[CurSlot, CurAmmo].AttackVoice, CurrentTeam^.voicepack);
-             case Ammo^[CurSlot, CurAmmo].AmmoType of
-                      amGrenade: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Bomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
+        if Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then
+           PlaySound(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack);
+             case CurAmmoType of
+                      amGrenade: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Bomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
                       amMolotov: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov,      0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
-                  amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
-                      amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
+                  amClusterBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
+                      amGasBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
                       amBazooka: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtAmmo_Grenade, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
                           amBee: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtBee,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
                       amShotgun: begin
@@ -207,12 +214,12 @@
                                  PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
                                  end;
                     amParachute: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
-                    // we save Ammo^[CurSlot, CurAmmo].Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
-                    amAirAttack: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 0, _0, _0, 0);
-                   amMineStrike: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 1, _0, _0, 0);
+                    // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
+                    amAirAttack: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
+                   amMineStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
                     amBlowTorch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
-                       amGirder: CurAmmoGear:= AddGear(0, 0, gtGirder, Ammo^[CurSlot, CurAmmo].Pos, _0, _0, 0);
-                     amTeleport: CurAmmoGear:= AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtTeleport, 0, _0, _0, 0);
+                       amGirder: CurAmmoGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+                     amTeleport: CurAmmoGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
                        amSwitch: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
                        amMortar: begin
                                  playSound(sndMortar);
@@ -225,9 +232,9 @@
                        amKamikaze: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtKamikaze, 0, xx * _0_5, yy * _0_5, 0);
                          amCake: CurAmmoGear:= AddGear(hwRound(lx) + hwSign(dX) * 3, hwRound(ly), gtCake, 0, xx, _0, 0);
                     amSeduction: CurAmmoGear:= AddGear(hwRound(lx + xx * cHHRadius * 2), hwRound(ly + yy * cHHRadius * 2), gtSeduction, 0, xx * _0_4, yy * _0_4, 0);
-                   amWatermelon: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, Ammo^[CurSlot, CurAmmo].Timer);
+                   amWatermelon: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon,  0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, CurWeapon^.Timer);
                   amHellishBomb: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtHellishBomb,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
-                       amNapalm: AddGear(Ammo^[CurSlot, CurAmmo].Pos, 0, gtAirAttack, 2, _0, _0, 0);
+                       amNapalm: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
                         amDrill: FollowGear:= AddGear(hwRound(lx), hwRound(ly), gtDrill, 0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
                       amBallgun: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun,  0, xx * _0_5, yy * _0_5, 0);
                     amJetpack: CurAmmoGear:= AddGear(hwRound(lx), hwRound(ly), gtJetpack, 0, _0, _0, 0);
@@ -258,7 +265,7 @@
                       amFlamethrower: CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
                   end;
 
-        uStats.AmmoUsed(Ammo^[CurSlot, CurAmmo].AmmoType);
+        uStats.AmmoUsed(CurAmmoType);
 
         if not (SpeechText = '') then
             begin
@@ -274,15 +281,14 @@
 
         Power:= 0;
         if (CurAmmoGear <> nil)
-           and (((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
+           and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
            begin
-           CurAmmoGear^.Ammo:= @(Ammo^[CurSlot, CurAmmo]);
-           CurAmmoGear^.AmmoType:= CurAmmoGear^.Ammo^.AmmoType;
+           CurAmmoGear^.AmmoType:= CurAmmoType;
            Message:= Message or gm_Attack;
            CurAmmoGear^.Message:= Message
            end else begin
            if not CurrentTeam^.ExtDriven and
-             ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_Power) <> 0) then SendIPC('a');
+             ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then SendIPC('a');
            AfterAttack;
            end
         end else Message:= Message and not gm_Attack;
@@ -296,27 +302,27 @@
         CurrentHedgehog^ do
     begin
     State:= State and not gstAttacking;
-    if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_Effect) = 0 then
+    if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Effect) = 0 then
         begin
         Inc(MultiShootAttacks);
         
-        if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) then
+        if (Ammoz[CurAmmoType].Ammo.NumPerTurn >= MultiShootAttacks) then
             begin
-            s:= inttostr(Ammo^[CurSlot, CurAmmo].NumPerTurn - MultiShootAttacks + 1);
+            s:= inttostr(Ammoz[CurAmmoType].Ammo.NumPerTurn - MultiShootAttacks + 1);
             AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
             end;
         
-        if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) or
+        if (Ammoz[CurAmmoType].Ammo.NumPerTurn >= MultiShootAttacks) or
             ((GameFlags and gfMultiWeapon) <> 0) then
             begin
             isInMultiShoot:= true
             end
         else
             begin
-            if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_NoRoundEndHint) = 0 then
+            if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEndHint) = 0 then
                 begin
                 OnUsedAmmo(CurrentHedgehog^);
-                TurnTimeLeft:= Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
+                TurnTimeLeft:= Ammoz[CurAmmoType].TimeAfterTurn;
                 State:= State or gstAttacked
                 end
             else
@@ -331,7 +337,7 @@
         OnUsedAmmo(CurrentHedgehog^);
         ApplyAmmoChanges(CurrentHedgehog^);
         end;
-    AttackBar:= 0;
+    AttackBar:= 0
     end
 end;
 
@@ -449,12 +455,14 @@
 
 procedure HedgehogStep(Gear: PGear);
 var PrevdX: LongInt;
+    CurWeapon: PAmmo;
 begin
+CurWeapon:= GetAmmoEntry(PHedgehog(Gear^.Hedgehog)^);
 if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
    begin
    if isCursorVisible then
       with PHedgehog(Gear^.Hedgehog)^ do
-        with Ammo^[CurSlot, CurAmmo] do
+        with CurWeapon^ do
           begin
           if (Gear^.Message and gm_Left  ) <> 0 then
              Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
@@ -583,7 +591,7 @@
 var da: LongWord;
 begin
 with PHedgehog(Gear^.Hedgehog)^ do
-    if (Ammo^[CurSlot, CurAmmo].AmmoType = amRope)
+    if (CurAmmoType = amRope)
     and ((Gear^.State and (gstMoving or gstHHJumping)) = gstMoving) then da:= 2 else da:= 1;
 
 if (((Gear^.Message and gm_Precise) = 0) or ((GameTicks mod 5) = 1)) then
@@ -702,7 +710,9 @@
 procedure doStepHedgehogDriven(Gear: PGear);
 var t: PGear;
     wasJumping: boolean;
+    Hedgehog: PHedgehog;
 begin
+Hedgehog:= PHedgehog(Gear^.Hedgehog);
 if not isInMultiShoot then
    AllInactive:= false
 else
@@ -722,7 +732,7 @@
 if (Gear^.State and gstAnimation) <> 0 then
     begin
     Gear^.Message:= 0;
-    if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack);
+    if (Gear^.Pos = Wavez[TWave(Gear^.Tag)].VoiceDelay) and (Gear^.Timer = 0) then PlaySound(Wavez[TWave(Gear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
     inc(Gear^.Timer);
     if Gear^.Timer = Wavez[TWave(Gear^.Tag)].Interval then
         begin
@@ -738,10 +748,10 @@
     or (StepTicks = cHHStepTicks)
     or (CurAmmoGear <> nil) then // we are moving
     begin
-    with PHedgehog(Gear^.Hedgehog)^ do
+    with Hedgehog^ do
         if (CurAmmoGear = nil)
         and (Gear^.dY > _0_39)
-        and (Ammo^[CurSlot, CurAmmo].AmmoType = amParachute) then Gear^.Message:= Gear^.Message or gm_Attack;
+        and (CurAmmoType = amParachute) then Gear^.Message:= Gear^.Message or gm_Attack;
     // check for case with ammo
     t:= CheckGearNear(Gear, gtCase, 36, 36);
     if t <> nil then
@@ -753,22 +763,23 @@
         or ((Gear^.State and gstAttacking) <> 0)) then
         Attack(Gear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
     else
-else with PHedgehog(Gear^.Hedgehog)^ do
-     if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
-        and ((Gear^.Message and gm_LJump) <> 0)
-        and (((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_AltUse) <> 0) then
-        begin
-        Gear^.Message:= Gear^.Message and not gm_LJump;
-        Attack(Gear)
-        end;
+else 
+    with Hedgehog^ do
+        if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
+            and ((Gear^.Message and gm_LJump) <> 0)
+            and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+            begin
+            Gear^.Message:= Gear^.Message and not gm_LJump;
+            Attack(Gear)
+            end;
 
 if (CurAmmoGear = nil)
-    or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) then
+    or ((Ammoz[Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) then
     begin
     if ((Gear^.Message and gm_Slot) <> 0) then
         begin
         ChangeAmmo(Gear);
-        ApplyAmmoChanges(PHedgehog(Gear^.Hedgehog)^)
+        ApplyAmmoChanges(Hedgehog^)
         end;
 
     if ((Gear^.Message and gm_Weapon) <> 0) then HHSetWeapon(Gear);
@@ -797,7 +808,7 @@
             Gear^.State:= Gear^.State or gstHHHJump;
             Gear^.dY:= -_0_25;
             if not cArtillery then Gear^.dX:= -SignAs(_0_02, Gear^.dX);
-            PlaySound(sndJump2, PHedgehog(Gear^.Hedgehog)^.Team^.voicepack)
+            PlaySound(sndJump2, Hedgehog^.Team^.voicepack)
             end;
 
     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);