fix line endings
authornemo
Tue, 17 Jan 2012 09:20:16 -0500
changeset 6581 e510d1245bd7
parent 6580 6155187bf599
child 6582 d32b5fde9ea6
fix line endings
hedgewars/uGearsHedgehog.pas
hedgewars/uGearsList.pas
hedgewars/uGearsUtils.pas
--- a/hedgewars/uGearsHedgehog.pas	Tue Jan 17 09:01:31 2012 -0500
+++ b/hedgewars/uGearsHedgehog.pas	Tue Jan 17 09:20:16 2012 -0500
@@ -1,1258 +1,1258 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-{$INCLUDE "options.inc"}
-
-unit uGearsHedgehog;
-interface
-uses uTypes;
-
-procedure doStepHedgehog(Gear: PGear);
-procedure AfterAttack; 
-procedure HedgehogStep(Gear: PGear); 
-procedure doStepHedgehogMoving(Gear: PGear); 
-procedure HedgehogChAngle(HHGear: PGear); 
-procedure PickUp(HH, Gear: PGear);
-
-implementation
-uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, uMisc, 
-    uCommands, uLocale, uUtils, uVisualGears, uStats, uIO, uScript,
-    uGearsList, uGears, uCollisions, uRandom, uStore, uTeams, 
-    uGearsUtils;
-
-// Shouldn't more of this ammo switching stuff be moved to uAmmos ?
-function ChangeAmmo(HHGear: PGear): boolean;
-var slot, i: Longword;
-    ammoidx: LongInt;
-begin
-ChangeAmmo:= false;
-slot:= HHGear^.MsgParam;
-
-with HHGear^.Hedgehog^ do
-    begin
-    HHGear^.Message:= HHGear^.Message and (not gmSlot);
-    ammoidx:= 0;
-    if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0)
-    or ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0))
-    or ((HHGear^.State and gstHHDriven) = 0) then
-        exit;
-    ChangeAmmo:= true;
-
-    while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do
-        inc(ammoidx);
-
-    if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then
-        OnUsedAmmo(HHGear^.Hedgehog^);
-
-    MultiShootAttacks:= 0;
-    HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump));
-    
-    if Ammoz[CurAmmoType].Slot = slot then
-        begin
-        i:= 0;
-        repeat
-        inc(ammoidx);
-        if (ammoidx > cMaxSlotAmmoIndex) then
-            begin
-            inc(i);
-            CurAmmoType:= amNothing;
-            ammoidx:= -1;
-            //TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
-            end;
-        until (i = 1) or ((Ammo^[slot, ammoidx].Count > 0)
-        and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns))
-        
-        end 
-    else
-        begin
-        i:= 0;
-        // check whether there is ammo in slot
-        while (i <= cMaxSlotAmmoIndex) and ((Ammo^[slot, i].Count = 0)
-        or (Team^.Clan^.TurnNumber <= Ammoz[Ammo^[slot, i].AmmoType].SkipTurns))
-            do inc(i);
-
-        if i <= cMaxSlotAmmoIndex then
-            ammoidx:= i
-        else ammoidx:= -1
-        end;
-        if ammoidx >= 0 then
-            CurAmmoType:= Ammo^[slot, ammoidx].AmmoType;
-    end
-end;
-
-procedure HHSetWeapon(HHGear: PGear);
-var t: LongInt;
-    weap: TAmmoType;
-    Hedgehog: PHedgehog;
-    s: boolean;
-begin
-s:= false;
-
-weap:= TAmmoType(HHGear^.MsgParam);
-Hedgehog:= HHGear^.Hedgehog;
-
-if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then
-    exit; // weapon is not activated yet
-
-HHGear^.MsgParam:= Ammoz[weap].Slot;
-
-t:= cMaxSlotAmmoIndex;
-
-HHGear^.Message:= HHGear^.Message and (not gmWeapon);
-
-with Hedgehog^ do
-    while (CurAmmoType <> weap) and (t >= 0) do
-        begin
-        s:= ChangeAmmo(HHGear);
-        dec(t)
-        end;
-
-if s then
-    ApplyAmmoChanges(HHGear^.Hedgehog^)
-end;
-
-procedure HHSetTimer(Gear: PGear);
-var CurWeapon: PAmmo;
-    color: LongWord;
-begin
-Gear^.Message:= Gear^.Message and (not gmTimer);
-CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
-with Gear^.Hedgehog^ do
-    if ((Gear^.Message and gmPrecise) <> 0) and ((CurWeapon^.Propz and ammoprop_SetBounce) <> 0) then
-        begin
-        color:= Gear^.Hedgehog^.Team^.Clan^.Color;
-        case Gear^.MsgParam of
-            1: begin
-               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce1]), color, capgrpAmmostate);
-               CurWeapon^.Bounciness:= 350;
-               end;
-            2: begin
-               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce2]), color, capgrpAmmostate);
-               CurWeapon^.Bounciness:= 700;
-               end;
-            3: begin
-               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce3]), color, capgrpAmmostate);
-               CurWeapon^.Bounciness:= 1000;
-               end;
-            4: begin
-               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce4]), color, capgrpAmmostate);
-               CurWeapon^.Bounciness:= 2000;
-               end;
-            5: begin
-               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce5]), color, capgrpAmmostate);
-               CurWeapon^.Bounciness:= 4000;
-               end
-            end
-        end
-    else if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
-        begin
-        CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
-        with CurrentTeam^ do
-            ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
-        end;
-end;
-
-
-procedure Attack(Gear: PGear);
-var xx, yy, newDx, newDy, lx, ly: hwFloat;
-    speech: PVisualGear;
-    newGear:  PGear;
-    CurWeapon: PAmmo;
-    altUse: boolean;
-    elastic: hwFloat;
-begin
-newGear:= nil;
-bShowFinger:= false;
-CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
-with Gear^,
-    Gear^.Hedgehog^ do
-        begin
-        if ((State and gstHHDriven) <> 0) and ((State and (gstAttacked or gstHHChooseTarget)) = 0) and (((State and gstMoving) = 0)
-        or (Power > 0)
-        or (CurAmmoType = amTeleport)
-        or 
-        // Allow attacks while moving on ammo with AltAttack
-        ((CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0))
-        or ((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 gmAttack)
-            else if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0 then
-                Message:= Message and (not gmAttack)
-            else
-                begin
-                if Power = 0 then
-                    begin
-                    AttackBar:= CurrentTeam^.AttackBar;
-                    PlaySound(sndThrowPowerUp)
-                    end;
-                inc(Power)
-                end;
-        if ((Message and gmAttack) <> 0) then
-            exit;
-
-        if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then
-            begin
-            StopSound(sndThrowPowerUp);
-            PlaySound(sndThrowRelease);
-            end;
-
-        xx:= SignAs(AngleSin(Angle), dX);
-        yy:= -AngleCos(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 Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then
-            AddVoice(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack);
-
-// Initiating alt attack
-        if  (CurAmmoGear <> nil)
-        and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
-        and ((Gear^.Message and gmLJump) <> 0)
-        and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
-            begin
-            newDx:= dX / _2; 
-            newDy:= dY / _2;
-            altUse:= true;
-            end
-        else
-            begin
-            newDx:= xx*Power/cPowerDivisor;
-            newDy:= yy*Power/cPowerDivisor;
-            altUse:= false
-            end;
-
-             case CurAmmoType of
-                      amGrenade: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGrenade,         0, newDx, newDy, CurWeapon^.Timer);
-                      amMolotov: newGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov,      0, newDx, newDy, 0);
-                  amClusterBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, newDx, newDy, CurWeapon^.Timer);
-                      amGasBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,      0, newDx, newDy, CurWeapon^.Timer);
-                      amBazooka: newGear:= AddGear(hwRound(lx), hwRound(ly), gtShell,        0, newDx, newDy, 0);
-                     amSnowball: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSnowball,     0, newDx, newDy, 0);
-                          amBee: newGear:= AddGear(hwRound(lx), hwRound(ly), gtBee,          0, newDx, newDy, 0);
-                      amShotgun: begin
-                                 PlaySound(sndShotgunReload);
-                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
-                                 end;
-                   amPickHammer: newGear:= AddGear(hwRound(lx), hwRound(ly) + cHHRadius, gtPickHammer, 0, _0, _0, 0);
-                         amSkip: ParseCommand('/skip', true);
-                         amRope: newGear:= AddGear(hwRound(lx), hwRound(ly), gtRope, 0, xx, yy, 0);
-                         amMine: if altUse then
-                                     newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, newDx, newDy, 3000)
-                                 else
-                                     newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000);
-                        amSMine: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSMine,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
-                       amDEagle: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
-                      amSineGun: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0);
-                    amPortalGun: begin
-                                 newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 
-                                 // set selected color
-                                 CurWeapon^.Pos);
-                                 end;
-                  amSniperRifle: begin
-                                 PlaySound(sndSniperReload);
-                                 newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
-                                 end;
-                     amDynamite: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDynamite, 0, SignAs(_0_03, dX), _0, 5000);
-                    amFirePunch: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtFirePunch, 0, xx, _0, 0);
-                         amWhip: begin
-                                 newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtWhip, 0, SignAs(_1, dX), - _0_8, 0);
-                                 PlaySound(sndWhipCrack)
-                                 end;
-                       amHammer: begin
-                                 newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtHammer, 0, SignAs(_1, dX), - _0_8, 0);
-                                 PlaySound(sndWhack)
-                                 end;
-                  amBaseballBat: begin
-                                 newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
-                                 PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
-                                 end;
-                    amParachute: begin
-                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
-                                 PlaySound(sndParachute)
-                                 end;
-                    // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
-                    amAirAttack: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
-                   amMineStrike: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
-                  amDrillStrike: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 3, _0, _0, CurWeapon^.Timer);
-                       amNapalm: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
-                    amBlowTorch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
-                       amGirder: newGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
-                     amTeleport: newGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
-                       amSwitch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
-                       amMortar: begin
-                                 playSound(sndMortar);
-                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtMortar,  0, xx*cMaxPower/cPowerDivisor, yy*cMaxPower/cPowerDivisor, 0);
-                                 end;
-                      amRCPlane: begin
-                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtRCPlane,  0, xx * cMaxPower / cPowerDivisor / 4, yy * cMaxPower / cPowerDivisor / 4, 0);
-                                 newGear^.SoundChannel:= LoopSound(sndRCPlane, nil)
-                                 end;
-                     amKamikaze: newGear:= AddGear(hwRound(lx), hwRound(ly), gtKamikaze, 0, xx * _0_5, yy * _0_5, 0);
-                         amCake: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 3, hwRound(ly), gtCake, 0, xx, _0, 0);
-                    amSeduction: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSeduction, 0, _0, _0, 0);
-                   amWatermelon: newGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon,  0, newDx, newDy, CurWeapon^.Timer);
-                  amHellishBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtHellishBomb,    0, newDx, newDy, 0);
-                        amDrill: newGear:= AddGear(hwRound(lx), hwRound(ly), gtDrill, 0, newDx, newDy, 0);
-                      amBallgun: newGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun,  0, xx * _0_5, yy * _0_5, 0);
-                      amJetpack: newGear:= AddGear(hwRound(lx), hwRound(ly), gtJetpack, 0, _0, _0, 0);
-                        amBirdy: begin
-                             PlaySound(sndWhistle);
-                             newGear:= AddGear(hwRound(lx), hwRound(ly) - 32, gtBirdy, 0, _0, _0, 0);
-                             end;
-                   amLowGravity: begin
-                                 PlaySound(sndLowGravity);
-                                 cGravity:= cMaxWindSpeed;
-                                 cGravityf:= 0.00025
-                                 end;
-                  amExtraDamage: begin 
-                                 PlaySound(sndHellishImpact4);
-                                 cDamageModifier:= _1_5
-                                 end;
-                 amInvulnerable: Invulnerable:= true;
-                    amExtraTime: begin
-                                 PlaySound(sndSwitchHog);
-                                 TurnTimeLeft:= TurnTimeLeft + 30000
-                                 end;
-                   amLaserSight: cLaserSighting:= true;
-                     amVampiric: begin
-                                 PlaySound(sndOw1, Team^.voicepack);
-                                 cVampiric:= true;
-                                 end;
-                        amPiano: begin
-                                 // Tuck the hedgehog away until the piano attack is completed
-                                 Unplaced:= true;
-                                 X:= _0;
-                                 Y:= _0;
-                                 newGear:= AddGear(TargetPoint.X, 0, gtPiano, 0, _0, _0, 0);
-                                 PauseMusic
-                                 end;
-                 amFlamethrower: newGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
-                      amLandGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtLandGun,  0, xx * _0_5, yy * _0_5, 0);
-                  amResurrector: begin
-                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtResurrector, 0, _0, _0, 0);
-                                 newGear^.SoundChannel := LoopSound(sndResurrector);
-                                 end;
-                                 //amMelonStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 4, _0, _0, 0);
-                    amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
-                       amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
-             end;
-             
-             case CurAmmoType of
-                      amGrenade, amMolotov, 
-                  amClusterBomb, amGasBomb, 
-                      amBazooka, amSnowball, 
-                          amBee, amSMine,
-                       amMortar, amWatermelon,
-                  amHellishBomb, amDrill: FollowGear:= newGear;
-
-                      amShotgun, amPickHammer,
-                         amRope, amDEagle,
-                      amSineGun, amSniperRifle,
-                    amFirePunch, amWhip,
-                       amHammer, amBaseballBat,
-                    amParachute, amBlowTorch,
-                       amGirder, amTeleport,
-                       amSwitch, amRCPlane,
-                     amKamikaze, amCake,
-                    amSeduction, amBallgun,
-                      amJetpack, amBirdy,
-                 amFlamethrower, amLandGun,
-                  amResurrector, amStructure,
-                       amTardis, amPiano: CurAmmoGear:= newGear;
-             end;
-             
-            if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then
-                newGear^.FlightTime:= GameTicks + 1000
-            else if CurAmmoType = amDrill then
-                newGear^.FlightTime:= GameTicks + 250;
-        if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
-            begin
-            newGear^.Target.X:= TargetPoint.X;
-            newGear^.Target.Y:= TargetPoint.Y
-            end;
-
-        // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement
-        if altUse then
-            FollowGear:= nil;
-
-        if (newGear <> nil) and ((Ammoz[newGear^.AmmoType].Ammo.Propz and ammoprop_SetBounce) <> 0) then
-            begin
-            elastic:=  int2hwfloat(CurWeapon^.Bounciness) / _1000;
-
-            if elastic < _1 then
-                newGear^.Elasticity:= newGear^.Elasticity * elastic
-            else if elastic > _1 then
-                newGear^.Elasticity:= _1 - ((_1-newGear^.Elasticity) / elastic);
-(* Experimented with friction modifier. Didn't seem helpful 
-            fric:= int2hwfloat(CurWeapon^.Bounciness) / _250;
-            if fric < _1 then newGear^.Friction:= newGear^.Friction * fric
-            else if fric > _1 then newGear^.Friction:= _1 - ((_1-newGear^.Friction) / fric)*)
-            end;
-
-
-        uStats.AmmoUsed(CurAmmoType);
-
-        if not (SpeechText = '') then
-            begin
-            speech:= AddVisualGear(0, 0, vgtSpeechBubble);
-            if speech <> nil then
-                begin
-                speech^.Text:= SpeechText;
-                speech^.Hedgehog:= Gear^.Hedgehog;
-                speech^.FrameTicks:= SpeechType;
-                end;
-            SpeechText:= ''
-            end;
-
-        Power:= 0;
-        if (CurAmmoGear <> nil)
-            and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
-            begin
-            Message:= Message or gmAttack;
-            CurAmmoGear^.Message:= Message
-            end
-        else
-            begin
-            if not CurrentTeam^.ExtDriven
-            and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then
-                SendIPC('a');
-            AfterAttack;
-            end
-        end
-    else 
-        Message:= Message and (not gmAttack);
-    end;
-    TargetPoint.X := NoPointX;
-    ScriptCall('onHogAttack');
-end;
-
-procedure AfterAttack;
-var s: shortstring;
-    a: TAmmoType;
-begin
-with CurrentHedgehog^.Gear^, CurrentHedgehog^ do
-    begin
-    a:= CurAmmoType;
-    State:= State and (not gstAttacking);
-    if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then
-        begin
-        Inc(MultiShootAttacks);
-        
-        if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) then
-            begin
-            s:= inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1);
-            AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
-            end;
-        
-        if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks)
-        or ((GameFlags and gfMultiWeapon) <> 0) then
-            begin
-            isInMultiShoot:= true
-            end
-        else
-            begin
-            OnUsedAmmo(CurrentHedgehog^);
-            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (((GameFlags and gfInfAttack) = 0) or PlacingHogs) then
-                begin
-                if TagTurnTimeLeft = 0 then
-                    TagTurnTimeLeft:= TurnTimeLeft;
-                TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
-                end;
-            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) then
-                State:= State or gstAttacked;
-            if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then
-                ApplyAmmoChanges(CurrentHedgehog^)
-            end;
-        end
-    else
-        begin
-        OnUsedAmmo(CurrentHedgehog^);
-        ApplyAmmoChanges(CurrentHedgehog^);
-        end;
-    AttackBar:= 0
-    end
-end;
-
-////////////////////////////////////////////////////////////////////////////////
-procedure doStepHedgehogDead(Gear: PGear);
-const frametime = 200;
-      timertime = frametime * 6;
-begin
-if Gear^.Hedgehog^.Unplaced then
-    exit;
-if Gear^.Timer > 1 then
-    begin
-    AllInactive:= false;
-    dec(Gear^.Timer);
-    if (Gear^.Timer mod frametime) = 0 then
-        inc(Gear^.Pos)
-    end 
-else if Gear^.Timer = 1 then
-    begin
-    Gear^.State:= Gear^.State or gstNoDamage;
-    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, CurrentHedgehog, EXPLAutoSound);
-    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0)^.Hedgehog:= Gear^.Hedgehog;
-    DeleteGear(Gear);
-    SetAllToActive
-    end 
-else // Gear^.Timer = 0
-    begin
-    AllInactive:= false;
-    Gear^.Z:= cCurrHHZ;
-    RemoveGearFromList(Gear);
-    InsertGearToList(Gear);
-    PlaySound(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
-    Gear^.Pos:= 0;
-    Gear^.Timer:= timertime
-    end
-end;
-
-////////////////////////////////////////////////////////////////////////////////
-procedure doStepHedgehogGone(Gear: PGear);
-const frametime = 65;
-      timertime = frametime * 11;
-begin
-if Gear^.Hedgehog^.Unplaced then
-    exit;
-if Gear^.Timer > 1 then
-    begin
-    AllInactive:= false;
-    dec(Gear^.Timer);
-    if (Gear^.Timer mod frametime) = 0 then
-        inc(Gear^.Pos)
-    end
-else
-if Gear^.Timer = 1 then
-    begin
-    DeleteGear(Gear);
-    SetAllToActive
-    end
-else // Gear^.Timer = 0
-    begin
-    AllInactive:= false;
-    Gear^.Z:= cCurrHHZ;
-    RemoveGearFromList(Gear);
-    InsertGearToList(Gear);
-    PlaySound(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
-    PlaySound(sndWarp);
-    Gear^.Pos:= 0;
-    Gear^.Timer:= timertime
-    end
-end;
-
-////////////////////////////////////////////////////////////////////////////////
-procedure PickUp(HH, Gear: PGear);
-var s: shortstring;
-    a: TAmmoType;
-    i: LongInt;
-    vga: PVisualGear;
-begin
-Gear^.Message:= gmDestroy;
-PlaySound(sndShotgunReload);
-if (Gear^.Pos and posCaseExplode) <> 0 then
-    if (Gear^.Pos and posCasePoison) <> 0 then
-        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned)
-    else
-        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound)
-else if (Gear^.Pos and posCasePoison) <> 0 then
-    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned + EXPLNoDamage)
-else
-case Gear^.Pos of
-       posCaseUtility,
-       posCaseAmmo: begin
-                    if Gear^.AmmoType <> amNothing then a:= Gear^.AmmoType 
-                    else
-                        begin
-                        for i:= 0 to GameTicks and $7F do
-                            GetRandom(2); // Burn some random numbers
-                        if Gear^.Pos = posCaseUtility then
-                            a:= GetUtility(HH^.Hedgehog)
-                        else
-                            a:= GetAmmo(HH^.Hedgehog)
-                        end;
-                    AddAmmo(HH^.Hedgehog^, a);
-// Possibly needs to check shared clan ammo game flag once added.
-// On the other hand, no obvious reason that clan members shouldn't know what ammo another clan member picked up
-                    if (not (HH^.Hedgehog^.Team^.ExtDriven 
-                    or (HH^.Hedgehog^.BotLevel > 0)))
-                    or (HH^.Hedgehog^.Team^.Clan^.ClanIndex = LocalClan)
-                    or (GameType = gmtDemo)  then
-                        begin
-                        s:= trammo[Ammoz[a].NameId] + ' (+' + IntToStr(Ammoz[a].NumberInCase) + ')';
-                        AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
-
-                        // show ammo icon
-                        vga:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtAmmo);
-                        if vga <> nil then
-                            vga^.Frame:= Longword(a);
-                        end;
-
-                    end;
-     posCaseHealth: begin
-                    inc(HH^.Health, Gear^.Health);
-                    HH^.Hedgehog^.Effects[hePoisoned] := false;
-                    str(Gear^.Health, s);
-                    s:= '+' + s;
-                    AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
-                    RenderHealth(HH^.Hedgehog^);
-                    RecountTeamHealth(HH^.Hedgehog^.Team);
-
-                    i:= 0;
-                    while i < Gear^.Health do
-                        begin
-                        vga:= AddVisualGear(hwRound(HH^.X), hwRound(HH^.Y), vgtStraightShot);
-                        if vga <> nil then
-                            with vga^ do
-                                begin
-                                Tint:= $00FF00FF;
-                                State:= ord(sprHealth)
-                                end;
-                        inc(i, 5);
-                        end;
-                    end;
-     end
-end;
-
-const StepTicks: LongWord = 0;
-
-procedure HedgehogStep(Gear: PGear);
-var PrevdX: LongInt;
-    CurWeapon: PAmmo;
-begin
-CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
-if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
-    begin
-    if isCursorVisible then
-        with Gear^.Hedgehog^ do
-            with CurWeapon^ do
-                begin
-                if (Gear^.Message and gmLeft  ) <> 0 then
-                    Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
-                else
-                    if (Gear^.Message and gmRight ) <> 0 then
-                        Pos:= (Pos + 1) mod Ammoz[AmmoType].PosCount
-    else
-        exit;
-    StepTicks:= 200;
-    exit
-    end;
-
-    if ((Gear^.Message and gmAnimate) <> 0) then
-        begin
-        Gear^.Message:= 0;
-        Gear^.State:= Gear^.State or gstAnimation;
-        Gear^.Tag:= Gear^.MsgParam;
-        Gear^.Timer:= 0;
-        Gear^.Pos:= 0
-        end;
-
-    if ((Gear^.Message and gmLJump ) <> 0) then
-        begin
-        Gear^.Message:= Gear^.Message and (not gmLJump);
-        DeleteCI(Gear);
-        if TestCollisionYwithGear(Gear, -1) = 0 then
-            if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
-                Gear^.Y:= Gear^.Y - _2
-            else
-                if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
-                    Gear^.Y:= Gear^.Y - _1;
-            if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
-            or   (TestCollisionYwithGear(Gear, -1) <> 0)) then
-                begin
-                Gear^.dY:= -_0_15;
-                if not cArtillery then
-                    Gear^.dX:= SignAs(_0_15, Gear^.dX);
-                Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
-                PlaySound(sndJump1, Gear^.Hedgehog^.Team^.voicepack);
-        exit
-        end;
-    end;
-
-    if ((Gear^.Message and gmHJump ) <> 0) then
-        begin
-        DeleteCI(Gear);
-        Gear^.Message:= Gear^.Message and (not gmHJump);
-
-        Gear^.dY:= -_0_2;
-        SetLittle(Gear^.dX);
-        Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
-        PlaySound(sndJump3, Gear^.Hedgehog^.Team^.voicepack);
-        exit
-        end;
-
-    PrevdX:= hwSign(Gear^.dX);
-    if (Gear^.Message and gmLeft  )<>0 then
-        Gear^.dX:= -cLittle else
-    if (Gear^.Message and gmRight )<>0 then
-        Gear^.dX:=  cLittle else exit;
-
-    if (Gear^.Message and (gmLeft or gmRight)) <> 0 then
-        begin
-        StepSoundTimer:= cHHStepTicks;
-        end;
-   
-    StepTicks:= cHHStepTicks;
-    if PrevdX <> hwSign(Gear^.dX) then
-        begin
-        FollowGear:= Gear;
-        exit
-        end;
-    DeleteCI(Gear); // must be after exit!! (see previous line)
-
-    Gear^.Hedgehog^.visStepPos:= (Gear^.Hedgehog^.visStepPos + 1) and 7;
-    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
-        begin
-        if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
-        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
-            Gear^.Y:= Gear^.Y - _1;
-        end;
-
-    if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then
-        Gear^.X:= Gear^.X + SignAs(_1, Gear^.dX);
-
-   SetAllHHToActive;
-
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y + _1;
-    if TestCollisionYwithGear(Gear, 1) = 0 then
-        begin
-        Gear^.Y:= Gear^.Y - _6;
-        Gear^.dY:= _0;
-        Gear^.State:= Gear^.State or gstMoving;
-        exit
-        end;
-        end
-        end
-        end
-        end
-        end
-        end;
-    AddGearCI(Gear)
-    end
-end;
-
-procedure HedgehogChAngle(HHGear: PGear);
-var da: LongWord;
-begin
-with HHGear^.Hedgehog^ do
-    if ((CurAmmoType = amRope) and ((HHGear^.State and (gstMoving or gstHHJumping)) = gstMoving))
-    or ((CurAmmoType = amPortalGun) and ((HHGear^.State and gstMoving) <> 0)) then
-        da:= 2
-    else da:= 1;
-
-if (((HHGear^.Message and gmPrecise) = 0) or ((GameTicks mod 5) = 1)) then
-    if ((HHGear^.Message and gmUp) <> 0) and (HHGear^.Angle >= CurMinAngle + da) then
-        dec(HHGear^.Angle, da)
-    else
-        if ((HHGear^.Message and gmDown) <> 0) and (HHGear^.Angle + da <= CurMaxAngle) then
-            inc(HHGear^.Angle, da)
-end;
-
-
-////////////////////////////////////////////////////////////////////////////////
-procedure doStepHedgehogMoving(Gear: PGear);
-var isFalling, isUnderwater: boolean;
-    land: Word;
-begin
-land:= 0;
-isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
-if Gear^.dX.QWordValue > 8160437862 then
-    Gear^.dX.QWordValue:= 8160437862;
-if Gear^.dY.QWordValue > 8160437862 then
-    Gear^.dY.QWordValue:= 8160437862;
-
-if Gear^.Hedgehog^.Unplaced then
-    begin
-    Gear^.dY:= _0;
-    Gear^.dX:= _0;
-    Gear^.State:= Gear^.State and (not gstMoving);
-    exit
-    end;
-isFalling:= (Gear^.dY.isNegative) or not TestCollisionYKick(Gear, 1);
-if isFalling then
-    begin
-    if (Gear^.dY.isNegative) and TestCollisionYKick(Gear, -1) then
-        Gear^.dY:= _0;
-    Gear^.State:= Gear^.State or gstMoving;
-    if (CurrentHedgehog^.Gear = Gear)
-        and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then 
-        begin
-        FollowGear:= Gear;
-        end;
-    if isUnderwater then
-       Gear^.dY:= Gear^.dY + cGravity / _2
-    else
-        begin
-        Gear^.dY:= Gear^.dY + cGravity;
-// this set of circumstances could be less complex if jumping was more clearly identified
-        if ((GameFlags and gfMoreWind) <> 0) and (((Gear^.Damage <> 0)
-        or ((CurAmmoGear <> nil) and ((CurAmmoGear^.AmmoType = amJetpack) or (CurAmmoGear^.AmmoType = amBirdy)))
-        or ((Gear^.dY.QWordValue + Gear^.dX.QWordValue) > _0_55.QWordValue))) then
-            Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
-        end
-    end 
-else
-    begin
-    land:= TestCollisionYwithGear(Gear, 1);
-    if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0)
-    and ((Gear^.State and gstHHJumping) <> 0) then
-        SetLittle(Gear^.dX);
-
-    if not Gear^.dY.isNegative then
-        begin
-        CheckHHDamage(Gear);
-
-        if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery)
-        and (Gear^.dX.QWordValue < _0_02.QWordValue) then
-            Gear^.dX.isNegative:= not Gear^.dX.isNegative; // landing after high jump
-        Gear^.State:= Gear^.State and (not (gstHHJumping or gstHHHJump));
-        Gear^.dY:= _0;
-        end
-    else
-        Gear^.dY:= Gear^.dY + cGravity;
-
-    if ((Gear^.State and gstMoving) <> 0) then
-        begin
-        if land and lfIce <> 0 then
-            begin
-            Gear^.dX:= Gear^.dX * (_1 - (_1 - Gear^.Friction) / _2)
-            end
-        else
-            Gear^.dX:= Gear^.dX * Gear^.Friction;
-        end
-    end;
-
-if (Gear^.State <> 0) then
-    DeleteCI(Gear);
-
-if isUnderwater then
-   begin
-   Gear^.dY:= Gear^.dY * _0_999;
-   Gear^.dX:= Gear^.dX * _0_999;
-   end;
-
-if (Gear^.State and gstMoving) <> 0 then
-    if TestCollisionXKick(Gear, hwSign(Gear^.dX)) then
-        if not isFalling then
-            if hwAbs(Gear^.dX) > _0_01 then
-                if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
-                    if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
-                        if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
-                        if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
-                        if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
-                        if hwAbs(Gear^.dX) > _0_02 then
-                            Gear^.dX:= -Gear^.Elasticity * Gear^.dX
-                        else
-                            begin
-                            Gear^.State:= Gear^.State and (not gstMoving);
-                            while TestCollisionYWithGear(Gear,1) = 0 do
-                                Gear^.Y:= Gear^.Y+_1;
-                            SetLittle(Gear^.dX)
-                            end
-            else
-                begin
-                Gear^.State:= Gear^.State and (not gstMoving);
-                while TestCollisionYWithGear(Gear,1) = 0 do
-                    Gear^.Y:= Gear^.Y+_1;
-                SetLittle(Gear^.dX)
-                end
-        else if (hwAbs(Gear^.dX) > cLittle)
-        and ((Gear^.State and gstHHJumping) = 0) then
-            Gear^.dX:= -Gear^.Elasticity * Gear^.dX
-        else
-            SetLittle(Gear^.dX);
-
-if (not isFalling)
-and (hwAbs(Gear^.dX) + hwAbs(Gear^.dY) < _0_03) then
-    begin
-    Gear^.State:= Gear^.State and (not gstWinner);
-    Gear^.State:= Gear^.State and (not gstMoving);
-    while TestCollisionYWithGear(Gear,1) = 0 do
-        Gear^.Y:= Gear^.Y+_1;
-    SetLittle(Gear^.dX);
-    Gear^.dY:= _0
-    end
-else
-    Gear^.State:= Gear^.State or gstMoving;
-
-if (Gear^.State and gstMoving) <> 0 then
-    begin
-    Gear^.State:= Gear^.State and (not gstAnimation);
-// ARTILLERY but not being moved by explosions
-    Gear^.X:= Gear^.X + Gear^.dX;
-    Gear^.Y:= Gear^.Y + Gear^.dY;
-    if (not Gear^.dY.isNegative) and (not TestCollisionYKick(Gear, 1)) 
-    and TestCollisionYwithXYShift(Gear, 0, 1, 1) then
-        begin
-        CheckHHDamage(Gear);
-        Gear^.dY:= _0;
-        Gear^.Y:= Gear^.Y + _1
-        end;
-    CheckGearDrowning(Gear);
-    // hide target cursor if current hog is drowning
-    if (Gear^.State and gstDrowning) <> 0 then
-        if (CurrentHedgehog^.Gear = Gear) then
-            isCursorVisible:= false
-    end;
-
-if (hwAbs(Gear^.dY) > _0) and (Gear^.FlightTime > 0) and ((GameFlags and gfLowGravity) = 0) then
-    begin
-    inc(Gear^.FlightTime);
-    if Gear^.FlightTime = 3000 then
-        begin
-        AddCaption(GetEventString(eidHomerun), cWhiteColor, capgrpMessage);
-        PlaySound(sndHomerun)
-        end;
-    end
-else
-    begin
-    uStats.hedgehogFlight(Gear, Gear^.FlightTime);
-    Gear^.FlightTime:= 0;
-    end;
-
-end;
-
-procedure doStepHedgehogDriven(HHGear: PGear);
-var t: PGear;
-    wasJumping: boolean;
-    Hedgehog: PHedgehog;
-begin
-Hedgehog:= HHGear^.Hedgehog;
-if isInMultiShoot then
-    HHGear^.Message:= 0;
-
-if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then 
-    AllInactive:= true
-else if not isInMultiShoot then
-    AllInactive:= false;
-
-if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then
-    begin
-    if TagTurnTimeLeft = 0 then
-        TagTurnTimeLeft:= TurnTimeLeft;
-    TurnTimeLeft:= 0;
-    isCursorVisible:= false;
-    HHGear^.State:= HHGear^.State and (not (gstHHDriven or gstAnimation or gstAttacking));
-    AttackBar:= 0;
-    if HHGear^.Damage > 0 then
-        HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
-    exit
-    end;
-
-if (HHGear^.State and gstAnimation) <> 0 then
-    begin
-    HHGear^.Message:= 0;
-    if (HHGear^.Pos = Wavez[TWave(HHGear^.Tag)].VoiceDelay) and (HHGear^.Timer = 0) then
-        PlaySound(Wavez[TWave(HHGear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
-    inc(HHGear^.Timer);
-    if HHGear^.Timer = Wavez[TWave(HHGear^.Tag)].Interval then
-        begin
-        HHGear^.Timer:= 0;
-        inc(HHGear^.Pos);
-        if HHGear^.Pos = Wavez[TWave(HHGear^.Tag)].FramesCount then
-            HHGear^.State:= HHGear^.State and (not gstAnimation)
-        end;
-    exit
-    end;
-
-if ((HHGear^.State and gstMoving) <> 0)
-or (StepTicks = cHHStepTicks)
-or (CurAmmoGear <> nil) then // we are moving
-    begin
-    with Hedgehog^ do
-        if (CurAmmoGear = nil)
-        and (HHGear^.dY > _0_39)
-        and (CurAmmoType = amParachute) then
-            HHGear^.Message:= HHGear^.Message or gmAttack;
-    // check for case with ammo
-    t:= CheckGearNear(HHGear, gtCase, 36, 36);
-    if t <> nil then
-        PickUp(HHGear, t)
-    end;
-
-if (CurAmmoGear = nil) then
-    if (((HHGear^.Message and gmAttack) <> 0)
-    or ((HHGear^.State and gstAttacking) <> 0)) then
-        Attack(HHGear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
-    else
-else 
-    with Hedgehog^ do
-        if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
-        and ((HHGear^.Message and gmLJump) <> 0)
-        and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
-            begin
-            Attack(HHGear);
-            HHGear^.Message:= HHGear^.Message and (not gmLJump)
-            end;
-
-if (CurAmmoGear = nil)
-or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) 
-or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) then
-    begin
-    if ((HHGear^.Message and gmSlot) <> 0) then
-        if ChangeAmmo(HHGear) then ApplyAmmoChanges(Hedgehog^);
-
-    if ((HHGear^.Message and gmWeapon) <> 0) then
-        HHSetWeapon(HHGear);
-
-    if ((HHGear^.Message and gmTimer) <> 0) then
-        HHSetTimer(HHGear);
-    end;
-
-if CurAmmoGear <> nil then
-    begin
-    CurAmmoGear^.Message:= HHGear^.Message;
-    exit
-    end;
-
-if not isInMultiShoot then
-    HedgehogChAngle(HHGear);
-
-if (HHGear^.State and gstMoving) <> 0 then
-    begin
-    wasJumping:= ((HHGear^.State and gstHHJumping) <> 0);
-
-    if ((HHGear^.Message and gmHJump) <> 0) and wasJumping and ((HHGear^.State and gstHHHJump) = 0) then
-        if (not (hwAbs(HHGear^.dX) > cLittle)) and (HHGear^.dY < -_0_02) then
-            begin
-            HHGear^.State:= HHGear^.State or gstHHHJump;
-            HHGear^.dY:= -_0_25;
-            if not cArtillery then
-                HHGear^.dX:= -SignAs(_0_02, HHGear^.dX);
-            PlaySound(sndJump2, Hedgehog^.Team^.voicepack)
-            end;
-
-    HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump));
-
-    if (not cArtillery) and wasJumping and TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
-        SetLittle(HHGear^.dX);
-
-    if Hedgehog^.Gear <> nil then
-        doStepHedgehogMoving(HHGear);
-
-    if ((HHGear^.State and (gstMoving or gstDrowning)) = 0) then
-        begin
-        AddGearCI(HHGear);
-        if wasJumping then
-            StepTicks:= 410
-        else
-            StepTicks:= 95
-        end;
-    exit
-    end;
-
-    if not isInMultiShoot and (Hedgehog^.Gear <> nil) then
-        begin
-        if StepTicks > 0 then
-            dec(StepTicks);
-        if (StepTicks = 0) then
-            HedgehogStep(HHGear)
-        end
-end;
-
-////////////////////////////////////////////////////////////////////////////////
-procedure doStepHedgehogFree(Gear: PGear);
-var prevState: Longword;
-begin
-prevState:= Gear^.State;
-
-doStepHedgehogMoving(Gear);
-
-if (Gear^.State and (gstMoving or gstDrowning)) <> 0 then
-    begin
-    if Gear^.Damage > 0 then
-        CalcRotationDirAngle(Gear);
-    AllInactive:= false;
-    exit
-    end;
-
-if (Gear^.Health = 0) then
-    begin
-    if PrvInactive or ((GameFlags and gfInfAttack) <> 0) then
-        begin
-        Gear^.Timer:= 0;
-        FollowGear:= Gear;
-        PrvInactive:= false;
-        AllInactive:= false;
-
-        if (Gear^.State and gstHHGone) = 0 then
-            begin
-            Gear^.Hedgehog^.Effects[hePoisoned] := false;
-            if Gear^.Hedgehog^.Effects[heResurrectable] then
-                begin
-                ResurrectHedgehog(Gear);
-                end
-            else 
-                begin
-                Gear^.State:= (Gear^.State or gstHHDeath) and (not gstAnimation);
-                Gear^.doStep:= @doStepHedgehogDead;
-                // Death message
-                AddCaption(Format(GetEventString(eidDied), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
-                end;
-            end
-        else
-            begin
-            Gear^.State:= Gear^.State and (not gstAnimation);
-            Gear^.doStep:= @doStepHedgehogGone;
-
-            // Gone message
-            AddCaption(Format(GetEventString(eidGone), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
-            end
-        end;
-    exit
-    end;
-
-if ((Gear^.State and gstWait) = 0) and
-    (prevState <> Gear^.State) then
-    begin
-    Gear^.State:= Gear^.State or gstWait;
-    Gear^.Timer:= 150
-    end
-else
-    begin
-    if Gear^.Timer = 0 then
-        begin
-        Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstHHChooseTarget));
-        Gear^.Active:= false;
-        AddGearCI(Gear);
-        exit
-        end
-    else dec(Gear^.Timer)
-    end;
-
-AllInactive:= false
-end;
-
-////////////////////////////////////////////////////////////////////////////////
-procedure doStepHedgehog(Gear: PGear);
-(*
-var x,y,tx,ty: LongInt;
-    tdX, tdY, slope: hwFloat; 
-    land: Word; *)
-var slope: hwFloat; 
-begin
-if (Gear^.Message and gmDestroy) <> 0 then
-    begin
-    DeleteGear(Gear);
-    exit
-    end;
-
-if (Gear^.State and gstHHDriven) = 0 then
-    doStepHedgehogFree(Gear)
-else
-    begin
-    with Gear^.Hedgehog^ do
-        if Team^.hasGone then
-            TeamGoneEffect(Team^)
-        else
-            doStepHedgehogDriven(Gear)
-    end;
-if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0)
-and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0)
-and (not Gear^.dY.isNegative) and (GameTicks mod (100*LongWOrd(hwRound(cMaxWindSpeed*2/cGravity))) = 0)
-and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
-    begin
-    slope:= CalcSlopeBelowGear(Gear);
-    Gear^.dX:=Gear^.dX+slope*_0_07;
-    if slope.QWordValue <> 0 then
-        Gear^.State:= Gear^.State or gstMoving;
-(*
-    x:= hwRound(Gear^.X);
-    y:= hwRound(Gear^.Y);
-    AddVisualGear(x, y, vgtSmokeTrace);
-    AddVisualGear(x - hwRound(_5*slope), y + hwRound(_5*slope), vgtSmokeTrace);
-    AddVisualGear(x + hwRound(_5*slope), y - hwRound(_5*slope), vgtSmokeTrace);
-    AddVisualGear(x - hwRound(_20 * slope), y + hwRound(_20 * slope), vgtSmokeTrace);
-    AddVisualGear(x + hwRound(_20 * slope), y - hwRound(_20 * slope), vgtSmokeTrace);
-    AddVisualGear(x - hwRound(_30 * slope), y + hwRound(_30 * slope), vgtSmokeTrace);
-    AddVisualGear(x + hwRound(_30 * slope), y - hwRound(_30 * slope), vgtSmokeTrace);
-    AddVisualGear(x - hwRound(_40 * slope), y + hwRound(_40 * slope), vgtSmokeTrace);
-    AddVisualGear(x + hwRound(_40 * slope), y - hwRound(_40 * slope), vgtSmokeTrace);
-    AddVisualGear(x - hwRound(_50 * slope), y + hwRound(_50 * slope), vgtSmokeTrace);
-    AddVisualGear(x + hwRound(_50 * slope), y - hwRound(_50 * slope), vgtSmokeTrace); *)
-    end
-end;
-
-end.
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit uGearsHedgehog;
+interface
+uses uTypes;
+
+procedure doStepHedgehog(Gear: PGear);
+procedure AfterAttack; 
+procedure HedgehogStep(Gear: PGear); 
+procedure doStepHedgehogMoving(Gear: PGear); 
+procedure HedgehogChAngle(HHGear: PGear); 
+procedure PickUp(HH, Gear: PGear);
+
+implementation
+uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, uMisc, 
+    uCommands, uLocale, uUtils, uVisualGears, uStats, uIO, uScript,
+    uGearsList, uGears, uCollisions, uRandom, uStore, uTeams, 
+    uGearsUtils;
+
+// Shouldn't more of this ammo switching stuff be moved to uAmmos ?
+function ChangeAmmo(HHGear: PGear): boolean;
+var slot, i: Longword;
+    ammoidx: LongInt;
+begin
+ChangeAmmo:= false;
+slot:= HHGear^.MsgParam;
+
+with HHGear^.Hedgehog^ do
+    begin
+    HHGear^.Message:= HHGear^.Message and (not gmSlot);
+    ammoidx:= 0;
+    if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0)
+    or ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0))
+    or ((HHGear^.State and gstHHDriven) = 0) then
+        exit;
+    ChangeAmmo:= true;
+
+    while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do
+        inc(ammoidx);
+
+    if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then
+        OnUsedAmmo(HHGear^.Hedgehog^);
+
+    MultiShootAttacks:= 0;
+    HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump));
+    
+    if Ammoz[CurAmmoType].Slot = slot then
+        begin
+        i:= 0;
+        repeat
+        inc(ammoidx);
+        if (ammoidx > cMaxSlotAmmoIndex) then
+            begin
+            inc(i);
+            CurAmmoType:= amNothing;
+            ammoidx:= -1;
+            //TryDo(i < 2, 'Engine bug: no ammo in current slot', true)
+            end;
+        until (i = 1) or ((Ammo^[slot, ammoidx].Count > 0)
+        and (Team^.Clan^.TurnNumber > Ammoz[Ammo^[slot, ammoidx].AmmoType].SkipTurns))
+        
+        end 
+    else
+        begin
+        i:= 0;
+        // check whether there is ammo in slot
+        while (i <= cMaxSlotAmmoIndex) and ((Ammo^[slot, i].Count = 0)
+        or (Team^.Clan^.TurnNumber <= Ammoz[Ammo^[slot, i].AmmoType].SkipTurns))
+            do inc(i);
+
+        if i <= cMaxSlotAmmoIndex then
+            ammoidx:= i
+        else ammoidx:= -1
+        end;
+        if ammoidx >= 0 then
+            CurAmmoType:= Ammo^[slot, ammoidx].AmmoType;
+    end
+end;
+
+procedure HHSetWeapon(HHGear: PGear);
+var t: LongInt;
+    weap: TAmmoType;
+    Hedgehog: PHedgehog;
+    s: boolean;
+begin
+s:= false;
+
+weap:= TAmmoType(HHGear^.MsgParam);
+Hedgehog:= HHGear^.Hedgehog;
+
+if Hedgehog^.Team^.Clan^.TurnNumber <= Ammoz[weap].SkipTurns then
+    exit; // weapon is not activated yet
+
+HHGear^.MsgParam:= Ammoz[weap].Slot;
+
+t:= cMaxSlotAmmoIndex;
+
+HHGear^.Message:= HHGear^.Message and (not gmWeapon);
+
+with Hedgehog^ do
+    while (CurAmmoType <> weap) and (t >= 0) do
+        begin
+        s:= ChangeAmmo(HHGear);
+        dec(t)
+        end;
+
+if s then
+    ApplyAmmoChanges(HHGear^.Hedgehog^)
+end;
+
+procedure HHSetTimer(Gear: PGear);
+var CurWeapon: PAmmo;
+    color: LongWord;
+begin
+Gear^.Message:= Gear^.Message and (not gmTimer);
+CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+with Gear^.Hedgehog^ do
+    if ((Gear^.Message and gmPrecise) <> 0) and ((CurWeapon^.Propz and ammoprop_SetBounce) <> 0) then
+        begin
+        color:= Gear^.Hedgehog^.Team^.Clan^.Color;
+        case Gear^.MsgParam of
+            1: begin
+               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce1]), color, capgrpAmmostate);
+               CurWeapon^.Bounciness:= 350;
+               end;
+            2: begin
+               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce2]), color, capgrpAmmostate);
+               CurWeapon^.Bounciness:= 700;
+               end;
+            3: begin
+               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce3]), color, capgrpAmmostate);
+               CurWeapon^.Bounciness:= 1000;
+               end;
+            4: begin
+               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce4]), color, capgrpAmmostate);
+               CurWeapon^.Bounciness:= 2000;
+               end;
+            5: begin
+               AddCaption(format(trmsg[sidBounce], trmsg[sidBounce5]), color, capgrpAmmostate);
+               CurWeapon^.Bounciness:= 4000;
+               end
+            end
+        end
+    else if (CurWeapon^.Propz and ammoprop_Timerable) <> 0 then
+        begin
+        CurWeapon^.Timer:= 1000 * Gear^.MsgParam;
+        with CurrentTeam^ do
+            ApplyAmmoChanges(Hedgehogs[CurrHedgehog]);
+        end;
+end;
+
+
+procedure Attack(Gear: PGear);
+var xx, yy, newDx, newDy, lx, ly: hwFloat;
+    speech: PVisualGear;
+    newGear:  PGear;
+    CurWeapon: PAmmo;
+    altUse: boolean;
+    elastic: hwFloat;
+begin
+newGear:= nil;
+bShowFinger:= false;
+CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+with Gear^,
+    Gear^.Hedgehog^ do
+        begin
+        if ((State and gstHHDriven) <> 0) and ((State and (gstAttacked or gstHHChooseTarget)) = 0) and (((State and gstMoving) = 0)
+        or (Power > 0)
+        or (CurAmmoType = amTeleport)
+        or 
+        // Allow attacks while moving on ammo with AltAttack
+        ((CurAmmoGear <> nil) and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0))
+        or ((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 gmAttack)
+            else if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) = 0 then
+                Message:= Message and (not gmAttack)
+            else
+                begin
+                if Power = 0 then
+                    begin
+                    AttackBar:= CurrentTeam^.AttackBar;
+                    PlaySound(sndThrowPowerUp)
+                    end;
+                inc(Power)
+                end;
+        if ((Message and gmAttack) <> 0) then
+            exit;
+
+        if (Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0 then
+            begin
+            StopSound(sndThrowPowerUp);
+            PlaySound(sndThrowRelease);
+            end;
+
+        xx:= SignAs(AngleSin(Angle), dX);
+        yy:= -AngleCos(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 Ammoz[CurAmmoType].Ammo.AttackVoice <> sndNone then
+            AddVoice(Ammoz[CurAmmoType].Ammo.AttackVoice, CurrentTeam^.voicepack);
+
+// Initiating alt attack
+        if  (CurAmmoGear <> nil)
+        and ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
+        and ((Gear^.Message and gmLJump) <> 0)
+        and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+            begin
+            newDx:= dX / _2; 
+            newDy:= dY / _2;
+            altUse:= true;
+            end
+        else
+            begin
+            newDx:= xx*Power/cPowerDivisor;
+            newDy:= yy*Power/cPowerDivisor;
+            altUse:= false
+            end;
+
+             case CurAmmoType of
+                      amGrenade: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGrenade,         0, newDx, newDy, CurWeapon^.Timer);
+                      amMolotov: newGear:= AddGear(hwRound(lx), hwRound(ly), gtMolotov,      0, newDx, newDy, 0);
+                  amClusterBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtClusterBomb,  0, newDx, newDy, CurWeapon^.Timer);
+                      amGasBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtGasBomb,      0, newDx, newDy, CurWeapon^.Timer);
+                      amBazooka: newGear:= AddGear(hwRound(lx), hwRound(ly), gtShell,        0, newDx, newDy, 0);
+                     amSnowball: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSnowball,     0, newDx, newDy, 0);
+                          amBee: newGear:= AddGear(hwRound(lx), hwRound(ly), gtBee,          0, newDx, newDy, 0);
+                      amShotgun: begin
+                                 PlaySound(sndShotgunReload);
+                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
+                                 end;
+                   amPickHammer: newGear:= AddGear(hwRound(lx), hwRound(ly) + cHHRadius, gtPickHammer, 0, _0, _0, 0);
+                         amSkip: ParseCommand('/skip', true);
+                         amRope: newGear:= AddGear(hwRound(lx), hwRound(ly), gtRope, 0, xx, yy, 0);
+                         amMine: if altUse then
+                                     newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, newDx, newDy, 3000)
+                                 else
+                                     newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000);
+                        amSMine: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSMine,    0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
+                       amDEagle: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
+                      amSineGun: newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0);
+                    amPortalGun: begin
+                                 newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 
+                                 // set selected color
+                                 CurWeapon^.Pos);
+                                 end;
+                  amSniperRifle: begin
+                                 PlaySound(sndSniperReload);
+                                 newGear:= AddGear(hwRound(lx + xx * cHHRadius), hwRound(ly + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
+                                 end;
+                     amDynamite: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtDynamite, 0, SignAs(_0_03, dX), _0, 5000);
+                    amFirePunch: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtFirePunch, 0, xx, _0, 0);
+                         amWhip: begin
+                                 newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtWhip, 0, SignAs(_1, dX), - _0_8, 0);
+                                 PlaySound(sndWhipCrack)
+                                 end;
+                       amHammer: begin
+                                 newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtHammer, 0, SignAs(_1, dX), - _0_8, 0);
+                                 PlaySound(sndWhack)
+                                 end;
+                  amBaseballBat: begin
+                                 newGear:= AddGear(hwRound(lx) + hwSign(dX) * 10, hwRound(ly), gtShover, gsttmpFlag, xx * _0_5, yy * _0_5, 0);
+                                 PlaySound(sndBaseballBat) // TODO: Only play if something is hit?
+                                 end;
+                    amParachute: begin
+                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtParachute, 0, _0, _0, 0);
+                                 PlaySound(sndParachute)
+                                 end;
+                    // we save CurWeapon^.Pos (in this case: cursor direction) by using it as (otherwise irrelevant) X value of the new gear.
+                    amAirAttack: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 0, _0, _0, 0);
+                   amMineStrike: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 1, _0, _0, 0);
+                  amDrillStrike: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 3, _0, _0, CurWeapon^.Timer);
+                       amNapalm: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
+                    amBlowTorch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
+                       amGirder: newGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+                     amTeleport: newGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
+                       amSwitch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
+                       amMortar: begin
+                                 playSound(sndMortar);
+                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtMortar,  0, xx*cMaxPower/cPowerDivisor, yy*cMaxPower/cPowerDivisor, 0);
+                                 end;
+                      amRCPlane: begin
+                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtRCPlane,  0, xx * cMaxPower / cPowerDivisor / 4, yy * cMaxPower / cPowerDivisor / 4, 0);
+                                 newGear^.SoundChannel:= LoopSound(sndRCPlane, nil)
+                                 end;
+                     amKamikaze: newGear:= AddGear(hwRound(lx), hwRound(ly), gtKamikaze, 0, xx * _0_5, yy * _0_5, 0);
+                         amCake: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 3, hwRound(ly), gtCake, 0, xx, _0, 0);
+                    amSeduction: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSeduction, 0, _0, _0, 0);
+                   amWatermelon: newGear:= AddGear(hwRound(lx), hwRound(ly), gtWatermelon,  0, newDx, newDy, CurWeapon^.Timer);
+                  amHellishBomb: newGear:= AddGear(hwRound(lx), hwRound(ly), gtHellishBomb,    0, newDx, newDy, 0);
+                        amDrill: newGear:= AddGear(hwRound(lx), hwRound(ly), gtDrill, 0, newDx, newDy, 0);
+                      amBallgun: newGear:= AddGear(hwRound(X), hwRound(Y), gtBallgun,  0, xx * _0_5, yy * _0_5, 0);
+                      amJetpack: newGear:= AddGear(hwRound(lx), hwRound(ly), gtJetpack, 0, _0, _0, 0);
+                        amBirdy: begin
+                             PlaySound(sndWhistle);
+                             newGear:= AddGear(hwRound(lx), hwRound(ly) - 32, gtBirdy, 0, _0, _0, 0);
+                             end;
+                   amLowGravity: begin
+                                 PlaySound(sndLowGravity);
+                                 cGravity:= cMaxWindSpeed;
+                                 cGravityf:= 0.00025
+                                 end;
+                  amExtraDamage: begin 
+                                 PlaySound(sndHellishImpact4);
+                                 cDamageModifier:= _1_5
+                                 end;
+                 amInvulnerable: Invulnerable:= true;
+                    amExtraTime: begin
+                                 PlaySound(sndSwitchHog);
+                                 TurnTimeLeft:= TurnTimeLeft + 30000
+                                 end;
+                   amLaserSight: cLaserSighting:= true;
+                     amVampiric: begin
+                                 PlaySound(sndOw1, Team^.voicepack);
+                                 cVampiric:= true;
+                                 end;
+                        amPiano: begin
+                                 // Tuck the hedgehog away until the piano attack is completed
+                                 Unplaced:= true;
+                                 X:= _0;
+                                 Y:= _0;
+                                 newGear:= AddGear(TargetPoint.X, 0, gtPiano, 0, _0, _0, 0);
+                                 PauseMusic
+                                 end;
+                 amFlamethrower: newGear:= AddGear(hwRound(X), hwRound(Y), gtFlamethrower,  0, xx * _0_5, yy * _0_5, 0);
+                      amLandGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtLandGun,  0, xx * _0_5, yy * _0_5, 0);
+                  amResurrector: begin
+                                 newGear:= AddGear(hwRound(lx), hwRound(ly), gtResurrector, 0, _0, _0, 0);
+                                 newGear^.SoundChannel := LoopSound(sndResurrector);
+                                 end;
+                                 //amMelonStrike: AddGear(CurWeapon^.Pos, 0, gtAirAttack, 4, _0, _0, 0);
+                    amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
+                       amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
+             end;
+             
+             case CurAmmoType of
+                      amGrenade, amMolotov, 
+                  amClusterBomb, amGasBomb, 
+                      amBazooka, amSnowball, 
+                          amBee, amSMine,
+                       amMortar, amWatermelon,
+                  amHellishBomb, amDrill: FollowGear:= newGear;
+
+                      amShotgun, amPickHammer,
+                         amRope, amDEagle,
+                      amSineGun, amSniperRifle,
+                    amFirePunch, amWhip,
+                       amHammer, amBaseballBat,
+                    amParachute, amBlowTorch,
+                       amGirder, amTeleport,
+                       amSwitch, amRCPlane,
+                     amKamikaze, amCake,
+                    amSeduction, amBallgun,
+                      amJetpack, amBirdy,
+                 amFlamethrower, amLandGun,
+                  amResurrector, amStructure,
+                       amTardis, amPiano: CurAmmoGear:= newGear;
+             end;
+             
+            if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then
+                newGear^.FlightTime:= GameTicks + 1000
+            else if CurAmmoType = amDrill then
+                newGear^.FlightTime:= GameTicks + 250;
+        if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
+            begin
+            newGear^.Target.X:= TargetPoint.X;
+            newGear^.Target.Y:= TargetPoint.Y
+            end;
+
+        // Clear FollowGear if using on a rope/parachute/saucer etc so focus stays with the hog's movement
+        if altUse then
+            FollowGear:= nil;
+
+        if (newGear <> nil) and ((Ammoz[newGear^.AmmoType].Ammo.Propz and ammoprop_SetBounce) <> 0) then
+            begin
+            elastic:=  int2hwfloat(CurWeapon^.Bounciness) / _1000;
+
+            if elastic < _1 then
+                newGear^.Elasticity:= newGear^.Elasticity * elastic
+            else if elastic > _1 then
+                newGear^.Elasticity:= _1 - ((_1-newGear^.Elasticity) / elastic);
+(* Experimented with friction modifier. Didn't seem helpful 
+            fric:= int2hwfloat(CurWeapon^.Bounciness) / _250;
+            if fric < _1 then newGear^.Friction:= newGear^.Friction * fric
+            else if fric > _1 then newGear^.Friction:= _1 - ((_1-newGear^.Friction) / fric)*)
+            end;
+
+
+        uStats.AmmoUsed(CurAmmoType);
+
+        if not (SpeechText = '') then
+            begin
+            speech:= AddVisualGear(0, 0, vgtSpeechBubble);
+            if speech <> nil then
+                begin
+                speech^.Text:= SpeechText;
+                speech^.Hedgehog:= Gear^.Hedgehog;
+                speech^.FrameTicks:= SpeechType;
+                end;
+            SpeechText:= ''
+            end;
+
+        Power:= 0;
+        if (CurAmmoGear <> nil)
+            and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then
+            begin
+            Message:= Message or gmAttack;
+            CurAmmoGear^.Message:= Message
+            end
+        else
+            begin
+            if not CurrentTeam^.ExtDriven
+            and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_Power) <> 0) then
+                SendIPC('a');
+            AfterAttack;
+            end
+        end
+    else 
+        Message:= Message and (not gmAttack);
+    end;
+    TargetPoint.X := NoPointX;
+    ScriptCall('onHogAttack');
+end;
+
+procedure AfterAttack;
+var s: shortstring;
+    a: TAmmoType;
+begin
+with CurrentHedgehog^.Gear^, CurrentHedgehog^ do
+    begin
+    a:= CurAmmoType;
+    State:= State and (not gstAttacking);
+    if (Ammoz[a].Ammo.Propz and ammoprop_Effect) = 0 then
+        begin
+        Inc(MultiShootAttacks);
+        
+        if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks) then
+            begin
+            s:= inttostr(Ammoz[a].Ammo.NumPerTurn - MultiShootAttacks + 1);
+            AddCaption(format(trmsg[sidRemaining], s), cWhiteColor, capgrpAmmostate);
+            end;
+        
+        if (Ammoz[a].Ammo.NumPerTurn >= MultiShootAttacks)
+        or ((GameFlags and gfMultiWeapon) <> 0) then
+            begin
+            isInMultiShoot:= true
+            end
+        else
+            begin
+            OnUsedAmmo(CurrentHedgehog^);
+            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) and (((GameFlags and gfInfAttack) = 0) or PlacingHogs) then
+                begin
+                if TagTurnTimeLeft = 0 then
+                    TagTurnTimeLeft:= TurnTimeLeft;
+                TurnTimeLeft:=(Ammoz[a].TimeAfterTurn * cGetAwayTime) div 100;
+                end;
+            if ((Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) = 0) then
+                State:= State or gstAttacked;
+            if (Ammoz[a].Ammo.Propz and ammoprop_NoRoundEnd) <> 0 then
+                ApplyAmmoChanges(CurrentHedgehog^)
+            end;
+        end
+    else
+        begin
+        OnUsedAmmo(CurrentHedgehog^);
+        ApplyAmmoChanges(CurrentHedgehog^);
+        end;
+    AttackBar:= 0
+    end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHedgehogDead(Gear: PGear);
+const frametime = 200;
+      timertime = frametime * 6;
+begin
+if Gear^.Hedgehog^.Unplaced then
+    exit;
+if Gear^.Timer > 1 then
+    begin
+    AllInactive:= false;
+    dec(Gear^.Timer);
+    if (Gear^.Timer mod frametime) = 0 then
+        inc(Gear^.Pos)
+    end 
+else if Gear^.Timer = 1 then
+    begin
+    Gear^.State:= Gear^.State or gstNoDamage;
+    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, CurrentHedgehog, EXPLAutoSound);
+    AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0)^.Hedgehog:= Gear^.Hedgehog;
+    DeleteGear(Gear);
+    SetAllToActive
+    end 
+else // Gear^.Timer = 0
+    begin
+    AllInactive:= false;
+    Gear^.Z:= cCurrHHZ;
+    RemoveGearFromList(Gear);
+    InsertGearToList(Gear);
+    PlaySound(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
+    Gear^.Pos:= 0;
+    Gear^.Timer:= timertime
+    end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHedgehogGone(Gear: PGear);
+const frametime = 65;
+      timertime = frametime * 11;
+begin
+if Gear^.Hedgehog^.Unplaced then
+    exit;
+if Gear^.Timer > 1 then
+    begin
+    AllInactive:= false;
+    dec(Gear^.Timer);
+    if (Gear^.Timer mod frametime) = 0 then
+        inc(Gear^.Pos)
+    end
+else
+if Gear^.Timer = 1 then
+    begin
+    DeleteGear(Gear);
+    SetAllToActive
+    end
+else // Gear^.Timer = 0
+    begin
+    AllInactive:= false;
+    Gear^.Z:= cCurrHHZ;
+    RemoveGearFromList(Gear);
+    InsertGearToList(Gear);
+    PlaySound(sndByeBye, Gear^.Hedgehog^.Team^.voicepack);
+    PlaySound(sndWarp);
+    Gear^.Pos:= 0;
+    Gear^.Timer:= timertime
+    end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure PickUp(HH, Gear: PGear);
+var s: shortstring;
+    a: TAmmoType;
+    i: LongInt;
+    vga: PVisualGear;
+begin
+Gear^.Message:= gmDestroy;
+PlaySound(sndShotgunReload);
+if (Gear^.Pos and posCaseExplode) <> 0 then
+    if (Gear^.Pos and posCasePoison) <> 0 then
+        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned)
+    else
+        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound)
+else if (Gear^.Pos and posCasePoison) <> 0 then
+    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned + EXPLNoDamage)
+else
+case Gear^.Pos of
+       posCaseUtility,
+       posCaseAmmo: begin
+                    if Gear^.AmmoType <> amNothing then a:= Gear^.AmmoType 
+                    else
+                        begin
+                        for i:= 0 to GameTicks and $7F do
+                            GetRandom(2); // Burn some random numbers
+                        if Gear^.Pos = posCaseUtility then
+                            a:= GetUtility(HH^.Hedgehog)
+                        else
+                            a:= GetAmmo(HH^.Hedgehog)
+                        end;
+                    AddAmmo(HH^.Hedgehog^, a);
+// Possibly needs to check shared clan ammo game flag once added.
+// On the other hand, no obvious reason that clan members shouldn't know what ammo another clan member picked up
+                    if (not (HH^.Hedgehog^.Team^.ExtDriven 
+                    or (HH^.Hedgehog^.BotLevel > 0)))
+                    or (HH^.Hedgehog^.Team^.Clan^.ClanIndex = LocalClan)
+                    or (GameType = gmtDemo)  then
+                        begin
+                        s:= trammo[Ammoz[a].NameId] + ' (+' + IntToStr(Ammoz[a].NumberInCase) + ')';
+                        AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
+
+                        // show ammo icon
+                        vga:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtAmmo);
+                        if vga <> nil then
+                            vga^.Frame:= Longword(a);
+                        end;
+
+                    end;
+     posCaseHealth: begin
+                    inc(HH^.Health, Gear^.Health);
+                    HH^.Hedgehog^.Effects[hePoisoned] := false;
+                    str(Gear^.Health, s);
+                    s:= '+' + s;
+                    AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
+                    RenderHealth(HH^.Hedgehog^);
+                    RecountTeamHealth(HH^.Hedgehog^.Team);
+
+                    i:= 0;
+                    while i < Gear^.Health do
+                        begin
+                        vga:= AddVisualGear(hwRound(HH^.X), hwRound(HH^.Y), vgtStraightShot);
+                        if vga <> nil then
+                            with vga^ do
+                                begin
+                                Tint:= $00FF00FF;
+                                State:= ord(sprHealth)
+                                end;
+                        inc(i, 5);
+                        end;
+                    end;
+     end
+end;
+
+const StepTicks: LongWord = 0;
+
+procedure HedgehogStep(Gear: PGear);
+var PrevdX: LongInt;
+    CurWeapon: PAmmo;
+begin
+CurWeapon:= GetAmmoEntry(Gear^.Hedgehog^);
+if ((Gear^.State and (gstAttacking or gstMoving)) = 0) then
+    begin
+    if isCursorVisible then
+        with Gear^.Hedgehog^ do
+            with CurWeapon^ do
+                begin
+                if (Gear^.Message and gmLeft  ) <> 0 then
+                    Pos:= (Pos - 1 + Ammoz[AmmoType].PosCount) mod Ammoz[AmmoType].PosCount
+                else
+                    if (Gear^.Message and gmRight ) <> 0 then
+                        Pos:= (Pos + 1) mod Ammoz[AmmoType].PosCount
+    else
+        exit;
+    StepTicks:= 200;
+    exit
+    end;
+
+    if ((Gear^.Message and gmAnimate) <> 0) then
+        begin
+        Gear^.Message:= 0;
+        Gear^.State:= Gear^.State or gstAnimation;
+        Gear^.Tag:= Gear^.MsgParam;
+        Gear^.Timer:= 0;
+        Gear^.Pos:= 0
+        end;
+
+    if ((Gear^.Message and gmLJump ) <> 0) then
+        begin
+        Gear^.Message:= Gear^.Message and (not gmLJump);
+        DeleteCI(Gear);
+        if TestCollisionYwithGear(Gear, -1) = 0 then
+            if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
+                Gear^.Y:= Gear^.Y - _2
+            else
+                if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
+                    Gear^.Y:= Gear^.Y - _1;
+            if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
+            or   (TestCollisionYwithGear(Gear, -1) <> 0)) then
+                begin
+                Gear^.dY:= -_0_15;
+                if not cArtillery then
+                    Gear^.dX:= SignAs(_0_15, Gear^.dX);
+                Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
+                PlaySound(sndJump1, Gear^.Hedgehog^.Team^.voicepack);
+        exit
+        end;
+    end;
+
+    if ((Gear^.Message and gmHJump ) <> 0) then
+        begin
+        DeleteCI(Gear);
+        Gear^.Message:= Gear^.Message and (not gmHJump);
+
+        Gear^.dY:= -_0_2;
+        SetLittle(Gear^.dX);
+        Gear^.State:= Gear^.State or gstMoving or gstHHJumping;
+        PlaySound(sndJump3, Gear^.Hedgehog^.Team^.voicepack);
+        exit
+        end;
+
+    PrevdX:= hwSign(Gear^.dX);
+    if (Gear^.Message and gmLeft  )<>0 then
+        Gear^.dX:= -cLittle else
+    if (Gear^.Message and gmRight )<>0 then
+        Gear^.dX:=  cLittle else exit;
+
+    if (Gear^.Message and (gmLeft or gmRight)) <> 0 then
+        begin
+        StepSoundTimer:= cHHStepTicks;
+        end;
+   
+    StepTicks:= cHHStepTicks;
+    if PrevdX <> hwSign(Gear^.dX) then
+        begin
+        FollowGear:= Gear;
+        exit
+        end;
+    DeleteCI(Gear); // must be after exit!! (see previous line)
+
+    Gear^.Hedgehog^.visStepPos:= (Gear^.Hedgehog^.visStepPos + 1) and 7;
+    if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) then
+        begin
+        if not (TestCollisionXwithXYShift(Gear, _0, -6, hwSign(Gear^.dX))
+        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            Gear^.Y:= Gear^.Y - _1;
+        if not (TestCollisionXwithXYShift(Gear, _0, -5, hwSign(Gear^.dX))
+        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            Gear^.Y:= Gear^.Y - _1;
+        if not (TestCollisionXwithXYShift(Gear, _0, -4, hwSign(Gear^.dX))
+        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            Gear^.Y:= Gear^.Y - _1;
+        if not (TestCollisionXwithXYShift(Gear, _0, -3, hwSign(Gear^.dX))
+        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            Gear^.Y:= Gear^.Y - _1;
+        if not (TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX))
+        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            Gear^.Y:= Gear^.Y - _1;
+        if not (TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX))
+        or (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            Gear^.Y:= Gear^.Y - _1;
+        end;
+
+    if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) and (not TestCollisionXwithGear(Gear, hwSign(Gear^.dX))) then
+        Gear^.X:= Gear^.X + SignAs(_1, Gear^.dX);
+
+   SetAllHHToActive;
+
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y + _1;
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y + _1;
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y + _1;
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y + _1;
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y + _1;
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y + _1;
+    if TestCollisionYwithGear(Gear, 1) = 0 then
+        begin
+        Gear^.Y:= Gear^.Y - _6;
+        Gear^.dY:= _0;
+        Gear^.State:= Gear^.State or gstMoving;
+        exit
+        end;
+        end
+        end
+        end
+        end
+        end
+        end;
+    AddGearCI(Gear)
+    end
+end;
+
+procedure HedgehogChAngle(HHGear: PGear);
+var da: LongWord;
+begin
+with HHGear^.Hedgehog^ do
+    if ((CurAmmoType = amRope) and ((HHGear^.State and (gstMoving or gstHHJumping)) = gstMoving))
+    or ((CurAmmoType = amPortalGun) and ((HHGear^.State and gstMoving) <> 0)) then
+        da:= 2
+    else da:= 1;
+
+if (((HHGear^.Message and gmPrecise) = 0) or ((GameTicks mod 5) = 1)) then
+    if ((HHGear^.Message and gmUp) <> 0) and (HHGear^.Angle >= CurMinAngle + da) then
+        dec(HHGear^.Angle, da)
+    else
+        if ((HHGear^.Message and gmDown) <> 0) and (HHGear^.Angle + da <= CurMaxAngle) then
+            inc(HHGear^.Angle, da)
+end;
+
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHedgehogMoving(Gear: PGear);
+var isFalling, isUnderwater: boolean;
+    land: Word;
+begin
+land:= 0;
+isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
+if Gear^.dX.QWordValue > 8160437862 then
+    Gear^.dX.QWordValue:= 8160437862;
+if Gear^.dY.QWordValue > 8160437862 then
+    Gear^.dY.QWordValue:= 8160437862;
+
+if Gear^.Hedgehog^.Unplaced then
+    begin
+    Gear^.dY:= _0;
+    Gear^.dX:= _0;
+    Gear^.State:= Gear^.State and (not gstMoving);
+    exit
+    end;
+isFalling:= (Gear^.dY.isNegative) or not TestCollisionYKick(Gear, 1);
+if isFalling then
+    begin
+    if (Gear^.dY.isNegative) and TestCollisionYKick(Gear, -1) then
+        Gear^.dY:= _0;
+    Gear^.State:= Gear^.State or gstMoving;
+    if (CurrentHedgehog^.Gear = Gear)
+        and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then 
+        begin
+        FollowGear:= Gear;
+        end;
+    if isUnderwater then
+       Gear^.dY:= Gear^.dY + cGravity / _2
+    else
+        begin
+        Gear^.dY:= Gear^.dY + cGravity;
+// this set of circumstances could be less complex if jumping was more clearly identified
+        if ((GameFlags and gfMoreWind) <> 0) and (((Gear^.Damage <> 0)
+        or ((CurAmmoGear <> nil) and ((CurAmmoGear^.AmmoType = amJetpack) or (CurAmmoGear^.AmmoType = amBirdy)))
+        or ((Gear^.dY.QWordValue + Gear^.dX.QWordValue) > _0_55.QWordValue))) then
+            Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
+        end
+    end 
+else
+    begin
+    land:= TestCollisionYwithGear(Gear, 1);
+    if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0)
+    and ((Gear^.State and gstHHJumping) <> 0) then
+        SetLittle(Gear^.dX);
+
+    if not Gear^.dY.isNegative then
+        begin
+        CheckHHDamage(Gear);
+
+        if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery)
+        and (Gear^.dX.QWordValue < _0_02.QWordValue) then
+            Gear^.dX.isNegative:= not Gear^.dX.isNegative; // landing after high jump
+        Gear^.State:= Gear^.State and (not (gstHHJumping or gstHHHJump));
+        Gear^.dY:= _0;
+        end
+    else
+        Gear^.dY:= Gear^.dY + cGravity;
+
+    if ((Gear^.State and gstMoving) <> 0) then
+        begin
+        if land and lfIce <> 0 then
+            begin
+            Gear^.dX:= Gear^.dX * (_1 - (_1 - Gear^.Friction) / _2)
+            end
+        else
+            Gear^.dX:= Gear^.dX * Gear^.Friction;
+        end
+    end;
+
+if (Gear^.State <> 0) then
+    DeleteCI(Gear);
+
+if isUnderwater then
+   begin
+   Gear^.dY:= Gear^.dY * _0_999;
+   Gear^.dX:= Gear^.dX * _0_999;
+   end;
+
+if (Gear^.State and gstMoving) <> 0 then
+    if TestCollisionXKick(Gear, hwSign(Gear^.dX)) then
+        if not isFalling then
+            if hwAbs(Gear^.dX) > _0_01 then
+                if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
+                    if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
+                        if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
+                        if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
+                        if not TestCollisionXwithXYShift(Gear, int2hwFloat(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
+                        if hwAbs(Gear^.dX) > _0_02 then
+                            Gear^.dX:= -Gear^.Elasticity * Gear^.dX
+                        else
+                            begin
+                            Gear^.State:= Gear^.State and (not gstMoving);
+                            while TestCollisionYWithGear(Gear,1) = 0 do
+                                Gear^.Y:= Gear^.Y+_1;
+                            SetLittle(Gear^.dX)
+                            end
+            else
+                begin
+                Gear^.State:= Gear^.State and (not gstMoving);
+                while TestCollisionYWithGear(Gear,1) = 0 do
+                    Gear^.Y:= Gear^.Y+_1;
+                SetLittle(Gear^.dX)
+                end
+        else if (hwAbs(Gear^.dX) > cLittle)
+        and ((Gear^.State and gstHHJumping) = 0) then
+            Gear^.dX:= -Gear^.Elasticity * Gear^.dX
+        else
+            SetLittle(Gear^.dX);
+
+if (not isFalling)
+and (hwAbs(Gear^.dX) + hwAbs(Gear^.dY) < _0_03) then
+    begin
+    Gear^.State:= Gear^.State and (not gstWinner);
+    Gear^.State:= Gear^.State and (not gstMoving);
+    while TestCollisionYWithGear(Gear,1) = 0 do
+        Gear^.Y:= Gear^.Y+_1;
+    SetLittle(Gear^.dX);
+    Gear^.dY:= _0
+    end
+else
+    Gear^.State:= Gear^.State or gstMoving;
+
+if (Gear^.State and gstMoving) <> 0 then
+    begin
+    Gear^.State:= Gear^.State and (not gstAnimation);
+// ARTILLERY but not being moved by explosions
+    Gear^.X:= Gear^.X + Gear^.dX;
+    Gear^.Y:= Gear^.Y + Gear^.dY;
+    if (not Gear^.dY.isNegative) and (not TestCollisionYKick(Gear, 1)) 
+    and TestCollisionYwithXYShift(Gear, 0, 1, 1) then
+        begin
+        CheckHHDamage(Gear);
+        Gear^.dY:= _0;
+        Gear^.Y:= Gear^.Y + _1
+        end;
+    CheckGearDrowning(Gear);
+    // hide target cursor if current hog is drowning
+    if (Gear^.State and gstDrowning) <> 0 then
+        if (CurrentHedgehog^.Gear = Gear) then
+            isCursorVisible:= false
+    end;
+
+if (hwAbs(Gear^.dY) > _0) and (Gear^.FlightTime > 0) and ((GameFlags and gfLowGravity) = 0) then
+    begin
+    inc(Gear^.FlightTime);
+    if Gear^.FlightTime = 3000 then
+        begin
+        AddCaption(GetEventString(eidHomerun), cWhiteColor, capgrpMessage);
+        PlaySound(sndHomerun)
+        end;
+    end
+else
+    begin
+    uStats.hedgehogFlight(Gear, Gear^.FlightTime);
+    Gear^.FlightTime:= 0;
+    end;
+
+end;
+
+procedure doStepHedgehogDriven(HHGear: PGear);
+var t: PGear;
+    wasJumping: boolean;
+    Hedgehog: PHedgehog;
+begin
+Hedgehog:= HHGear^.Hedgehog;
+if isInMultiShoot then
+    HHGear^.Message:= 0;
+
+if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then 
+    AllInactive:= true
+else if not isInMultiShoot then
+    AllInactive:= false;
+
+if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then
+    begin
+    if TagTurnTimeLeft = 0 then
+        TagTurnTimeLeft:= TurnTimeLeft;
+    TurnTimeLeft:= 0;
+    isCursorVisible:= false;
+    HHGear^.State:= HHGear^.State and (not (gstHHDriven or gstAnimation or gstAttacking));
+    AttackBar:= 0;
+    if HHGear^.Damage > 0 then
+        HHGear^.State:= HHGear^.State and (not (gstHHJumping or gstHHHJump));
+    exit
+    end;
+
+if (HHGear^.State and gstAnimation) <> 0 then
+    begin
+    HHGear^.Message:= 0;
+    if (HHGear^.Pos = Wavez[TWave(HHGear^.Tag)].VoiceDelay) and (HHGear^.Timer = 0) then
+        PlaySound(Wavez[TWave(HHGear^.Tag)].Voice, Hedgehog^.Team^.voicepack);
+    inc(HHGear^.Timer);
+    if HHGear^.Timer = Wavez[TWave(HHGear^.Tag)].Interval then
+        begin
+        HHGear^.Timer:= 0;
+        inc(HHGear^.Pos);
+        if HHGear^.Pos = Wavez[TWave(HHGear^.Tag)].FramesCount then
+            HHGear^.State:= HHGear^.State and (not gstAnimation)
+        end;
+    exit
+    end;
+
+if ((HHGear^.State and gstMoving) <> 0)
+or (StepTicks = cHHStepTicks)
+or (CurAmmoGear <> nil) then // we are moving
+    begin
+    with Hedgehog^ do
+        if (CurAmmoGear = nil)
+        and (HHGear^.dY > _0_39)
+        and (CurAmmoType = amParachute) then
+            HHGear^.Message:= HHGear^.Message or gmAttack;
+    // check for case with ammo
+    t:= CheckGearNear(HHGear, gtCase, 36, 36);
+    if t <> nil then
+        PickUp(HHGear, t)
+    end;
+
+if (CurAmmoGear = nil) then
+    if (((HHGear^.Message and gmAttack) <> 0)
+    or ((HHGear^.State and gstAttacking) <> 0)) then
+        Attack(HHGear) // should be before others to avoid desync with '/put' msg and changing weapon msgs
+    else
+else 
+    with Hedgehog^ do
+        if ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0)
+        and ((HHGear^.Message and gmLJump) <> 0)
+        and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) <> 0) then
+            begin
+            Attack(HHGear);
+            HHGear^.Message:= HHGear^.Message and (not gmLJump)
+            end;
+
+if (CurAmmoGear = nil)
+or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_AltAttack) <> 0) 
+or ((Ammoz[CurAmmoGear^.AmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) then
+    begin
+    if ((HHGear^.Message and gmSlot) <> 0) then
+        if ChangeAmmo(HHGear) then ApplyAmmoChanges(Hedgehog^);
+
+    if ((HHGear^.Message and gmWeapon) <> 0) then
+        HHSetWeapon(HHGear);
+
+    if ((HHGear^.Message and gmTimer) <> 0) then
+        HHSetTimer(HHGear);
+    end;
+
+if CurAmmoGear <> nil then
+    begin
+    CurAmmoGear^.Message:= HHGear^.Message;
+    exit
+    end;
+
+if not isInMultiShoot then
+    HedgehogChAngle(HHGear);
+
+if (HHGear^.State and gstMoving) <> 0 then
+    begin
+    wasJumping:= ((HHGear^.State and gstHHJumping) <> 0);
+
+    if ((HHGear^.Message and gmHJump) <> 0) and wasJumping and ((HHGear^.State and gstHHHJump) = 0) then
+        if (not (hwAbs(HHGear^.dX) > cLittle)) and (HHGear^.dY < -_0_02) then
+            begin
+            HHGear^.State:= HHGear^.State or gstHHHJump;
+            HHGear^.dY:= -_0_25;
+            if not cArtillery then
+                HHGear^.dX:= -SignAs(_0_02, HHGear^.dX);
+            PlaySound(sndJump2, Hedgehog^.Team^.voicepack)
+            end;
+
+    HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump));
+
+    if (not cArtillery) and wasJumping and TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+        SetLittle(HHGear^.dX);
+
+    if Hedgehog^.Gear <> nil then
+        doStepHedgehogMoving(HHGear);
+
+    if ((HHGear^.State and (gstMoving or gstDrowning)) = 0) then
+        begin
+        AddGearCI(HHGear);
+        if wasJumping then
+            StepTicks:= 410
+        else
+            StepTicks:= 95
+        end;
+    exit
+    end;
+
+    if not isInMultiShoot and (Hedgehog^.Gear <> nil) then
+        begin
+        if StepTicks > 0 then
+            dec(StepTicks);
+        if (StepTicks = 0) then
+            HedgehogStep(HHGear)
+        end
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHedgehogFree(Gear: PGear);
+var prevState: Longword;
+begin
+prevState:= Gear^.State;
+
+doStepHedgehogMoving(Gear);
+
+if (Gear^.State and (gstMoving or gstDrowning)) <> 0 then
+    begin
+    if Gear^.Damage > 0 then
+        CalcRotationDirAngle(Gear);
+    AllInactive:= false;
+    exit
+    end;
+
+if (Gear^.Health = 0) then
+    begin
+    if PrvInactive or ((GameFlags and gfInfAttack) <> 0) then
+        begin
+        Gear^.Timer:= 0;
+        FollowGear:= Gear;
+        PrvInactive:= false;
+        AllInactive:= false;
+
+        if (Gear^.State and gstHHGone) = 0 then
+            begin
+            Gear^.Hedgehog^.Effects[hePoisoned] := false;
+            if Gear^.Hedgehog^.Effects[heResurrectable] then
+                begin
+                ResurrectHedgehog(Gear);
+                end
+            else 
+                begin
+                Gear^.State:= (Gear^.State or gstHHDeath) and (not gstAnimation);
+                Gear^.doStep:= @doStepHedgehogDead;
+                // Death message
+                AddCaption(Format(GetEventString(eidDied), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
+                end;
+            end
+        else
+            begin
+            Gear^.State:= Gear^.State and (not gstAnimation);
+            Gear^.doStep:= @doStepHedgehogGone;
+
+            // Gone message
+            AddCaption(Format(GetEventString(eidGone), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
+            end
+        end;
+    exit
+    end;
+
+if ((Gear^.State and gstWait) = 0) and
+    (prevState <> Gear^.State) then
+    begin
+    Gear^.State:= Gear^.State or gstWait;
+    Gear^.Timer:= 150
+    end
+else
+    begin
+    if Gear^.Timer = 0 then
+        begin
+        Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstHHChooseTarget));
+        Gear^.Active:= false;
+        AddGearCI(Gear);
+        exit
+        end
+    else dec(Gear^.Timer)
+    end;
+
+AllInactive:= false
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepHedgehog(Gear: PGear);
+(*
+var x,y,tx,ty: LongInt;
+    tdX, tdY, slope: hwFloat; 
+    land: Word; *)
+var slope: hwFloat; 
+begin
+if (Gear^.Message and gmDestroy) <> 0 then
+    begin
+    DeleteGear(Gear);
+    exit
+    end;
+
+if (Gear^.State and gstHHDriven) = 0 then
+    doStepHedgehogFree(Gear)
+else
+    begin
+    with Gear^.Hedgehog^ do
+        if Team^.hasGone then
+            TeamGoneEffect(Team^)
+        else
+            doStepHedgehogDriven(Gear)
+    end;
+if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0)
+and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0)
+and (not Gear^.dY.isNegative) and (GameTicks mod (100*LongWOrd(hwRound(cMaxWindSpeed*2/cGravity))) = 0)
+and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
+    begin
+    slope:= CalcSlopeBelowGear(Gear);
+    Gear^.dX:=Gear^.dX+slope*_0_07;
+    if slope.QWordValue <> 0 then
+        Gear^.State:= Gear^.State or gstMoving;
+(*
+    x:= hwRound(Gear^.X);
+    y:= hwRound(Gear^.Y);
+    AddVisualGear(x, y, vgtSmokeTrace);
+    AddVisualGear(x - hwRound(_5*slope), y + hwRound(_5*slope), vgtSmokeTrace);
+    AddVisualGear(x + hwRound(_5*slope), y - hwRound(_5*slope), vgtSmokeTrace);
+    AddVisualGear(x - hwRound(_20 * slope), y + hwRound(_20 * slope), vgtSmokeTrace);
+    AddVisualGear(x + hwRound(_20 * slope), y - hwRound(_20 * slope), vgtSmokeTrace);
+    AddVisualGear(x - hwRound(_30 * slope), y + hwRound(_30 * slope), vgtSmokeTrace);
+    AddVisualGear(x + hwRound(_30 * slope), y - hwRound(_30 * slope), vgtSmokeTrace);
+    AddVisualGear(x - hwRound(_40 * slope), y + hwRound(_40 * slope), vgtSmokeTrace);
+    AddVisualGear(x + hwRound(_40 * slope), y - hwRound(_40 * slope), vgtSmokeTrace);
+    AddVisualGear(x - hwRound(_50 * slope), y + hwRound(_50 * slope), vgtSmokeTrace);
+    AddVisualGear(x + hwRound(_50 * slope), y - hwRound(_50 * slope), vgtSmokeTrace); *)
+    end
+end;
+
+end.
--- a/hedgewars/uGearsList.pas	Tue Jan 17 09:01:31 2012 -0500
+++ b/hedgewars/uGearsList.pas	Tue Jan 17 09:20:16 2012 -0500
@@ -1,565 +1,565 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-{$INCLUDE "options.inc"}
-unit uGearsList;
-
-interface
-uses uFloat, uTypes;
-
-function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
-procedure DeleteGear(Gear: PGear);
-procedure InsertGearToList(Gear: PGear);
-procedure RemoveGearFromList(Gear: PGear);
-
-implementation
-
-uses uRandom, uUtils, uConsts, uVariables, uAmmos, uTeams, uStats,
-    uTextures, uScript, uRenderUtils, uAI, uCollisions,
-    uGearsRender, uGearsUtils;
-
-procedure InsertGearToList(Gear: PGear);
-var tmp, ptmp: PGear;
-begin
-    tmp:= GearsList;
-    ptmp:= GearsList;
-    while (tmp <> nil) and (tmp^.Z <= Gear^.Z) do
-        begin
-        ptmp:= tmp;
-        tmp:= tmp^.NextGear
-        end;
-
-    if ptmp <> tmp then
-        begin
-        Gear^.NextGear:= ptmp^.NextGear;
-        Gear^.PrevGear:= ptmp;
-        if ptmp^.NextGear <> nil then
-            ptmp^.NextGear^.PrevGear:= Gear;
-        ptmp^.NextGear:= Gear
-        end
-    else
-        begin
-        Gear^.NextGear:= GearsList;
-        if Gear^.NextGear <> nil then
-            Gear^.NextGear^.PrevGear:= Gear;
-        GearsList:= Gear;
-        end;
-end;
-
-procedure RemoveGearFromList(Gear: PGear);
-begin
-if Gear^.NextGear <> nil then
-    Gear^.NextGear^.PrevGear:= Gear^.PrevGear;
-if Gear^.PrevGear <> nil then
-    Gear^.PrevGear^.NextGear:= Gear^.NextGear
-else
-    GearsList:= Gear^.NextGear
-end;
-    
-function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
-const Counter: Longword = 0;
-var gear: PGear;
-begin
-inc(Counter);
-AddFileLog('AddGear: #' + inttostr(Counter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
-
-New(gear);
-FillChar(gear^, sizeof(TGear), 0);
-gear^.X:= int2hwFloat(X);
-gear^.Y:= int2hwFloat(Y);
-gear^.Target.X:= NoPointX;
-gear^.Kind := Kind;
-gear^.State:= State;
-gear^.Active:= true;
-gear^.dX:= dX;
-gear^.dY:= dY;
-gear^.doStep:= doStepHandlers[Kind];
-gear^.CollisionIndex:= -1;
-gear^.Timer:= Timer;
-gear^.FlightTime:= 0;
-gear^.uid:= Counter;
-gear^.SoundChannel:= -1;
-gear^.ImpactSound:= sndNone;
-gear^.nImpactSounds:= 0;
-gear^.Density:= _1;
-// Define ammo association, if any.
-gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
-if Ammoz[Gear^.AmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
-    gear^.Z:= cHHZ+1
-else gear^.Z:= cUsualZ;
-
-if CurrentHedgehog <> nil then
-    begin
-    gear^.Hedgehog:= CurrentHedgehog;
-    gear^.IntersectGear:= CurrentHedgehog^.Gear
-    end;
-    
-case Kind of
-     gtGrenade,
-     gtClusterBomb,
-     gtGasBomb: begin
-                gear^.ImpactSound:= sndGrenadeImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.AdvBounce:= 1;
-                gear^.Radius:= 5;
-                gear^.Elasticity:= _0_8;
-                gear^.Friction:= _0_8;
-                gear^.Density:= _1_5;
-                gear^.RenderTimer:= true;
-                if gear^.Timer = 0 then
-                    gear^.Timer:= 3000
-                end;
-  gtWatermelon: begin
-                gear^.ImpactSound:= sndMelonImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.AdvBounce:= 1;
-                gear^.Radius:= 6;
-                gear^.Elasticity:= _0_8;
-                gear^.Friction:= _0_995;
-                gear^.Density:= _2;
-                gear^.RenderTimer:= true;
-                if gear^.Timer = 0 then
-                    gear^.Timer:= 3000
-                end;
-  gtMelonPiece: begin
-                gear^.Density:= _2;
-                end;
-    gtHedgehog: begin
-                gear^.AdvBounce:= 1;
-                gear^.Radius:= cHHRadius;
-                gear^.Elasticity:= _0_35;
-                gear^.Friction:= _0_999;
-                gear^.Angle:= cMaxAngle div 2;
-                gear^.Density:= _3;
-                gear^.Z:= cHHZ;
-                if (GameFlags and gfAISurvival) <> 0 then
-                    if gear^.Hedgehog^.BotLevel > 0 then
-                        gear^.Hedgehog^.Effects[heResurrectable] := true;
-                end;
-       gtShell: begin
-                gear^.Radius:= 4;
-                gear^.Density:= _1;
-                end;
-       gtSnowball: begin
-                gear^.ImpactSound:= sndMudballImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.Radius:= 4;
-                gear^.Elasticity:= _1;
-                gear^.Friction:= _1;
-                gear^.Density:= _0_5;
-                end;
-
-     gtFlake: begin
-                with Gear^ do
-                    begin
-                    Pos:= 0;
-                    Radius:= 1;
-                    DirAngle:= random * 360;
-                    if State and gstTmpFlag = 0 then
-                        begin
-                        dx.isNegative:= GetRandom(2) = 0;
-                        dx.QWordValue:= GetRandom(100000000);
-                        dy.isNegative:= false;
-                        dy.QWordValue:= GetRandom(70000000);
-                        if GetRandom(2) = 0 then
-                            dx := -dx
-                        end;
-                    State:= State or gstInvisible;
-                    Health:= random(vobFrameTicks);
-                    Timer:= random(vobFramesCount);
-                    Angle:= (random(2) * 2 - 1) * (1 + random(10000)) * vobVelocity
-                    end
-                end;
-       gtGrave: begin
-                gear^.ImpactSound:= sndGraveImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.Radius:= 10;
-                gear^.Elasticity:= _0_6;
-                end;
-         gtBee: begin
-                gear^.Radius:= 5;
-                gear^.Timer:= 500;
-                gear^.RenderTimer:= true;
-                gear^.Elasticity:= _0_9;
-                gear^.Tag:= 0;
-                end;
-   gtSeduction: begin
-                gear^.Radius:= 250;
-                end;
- gtShotgunShot: begin
-                gear^.Timer:= 900;
-                gear^.Radius:= 2
-                end;
-  gtPickHammer: begin
-                gear^.Radius:= 10;
-                gear^.Timer:= 4000
-                end;
-   gtHammerHit: begin
-                gear^.Radius:= 8;
-                gear^.Timer:= 125
-                end;
-        gtRope: begin
-                gear^.Radius:= 3;
-                gear^.Friction:= _450 * _0_01 * cRopePercent;
-                RopePoints.Count:= 0;
-                end;
-        gtMine: begin
-                gear^.ImpactSound:= sndMineImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.Health:= 10;
-                gear^.State:= gear^.State or gstMoving;
-                gear^.Radius:= 2;
-                gear^.Elasticity:= _0_55;
-                gear^.Friction:= _0_995;
-                gear^.Density:= _0_9;
-                if cMinesTime < 0 then
-                    gear^.Timer:= getrandom(51)*100
-                else
-                    gear^.Timer:= cMinesTime;
-                end;
-       gtSMine: begin
-                gear^.Health:= 10;
-                gear^.State:= gear^.State or gstMoving;
-                gear^.Radius:= 2;
-                gear^.Elasticity:= _0_55;
-                gear^.Friction:= _0_995;
-                gear^.Density:= _0_9;
-                gear^.Timer:= 500;
-                end;
-        gtCase: begin
-                gear^.ImpactSound:= sndGraveImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.Radius:= 16;
-                gear^.Elasticity:= _0_3
-                end;
-  gtExplosives: begin
-                gear^.ImpactSound:= sndGrenadeImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.Radius:= 16;
-                gear^.Elasticity:= _0_4;
-                gear^.Friction:= _0_995;
-                gear^.Density:= _6;
-                gear^.Health:= cBarrelHealth;
-                gear^.Z:= cHHZ-1
-                end;
-  gtDEagleShot: begin
-                gear^.Radius:= 1;
-                gear^.Health:= 50
-                end;
-  gtSniperRifleShot: begin
-                gear^.Radius:= 1;
-                gear^.Health:= 50
-                end;
-    gtDynamite: begin
-                gear^.Radius:= 3;
-                gear^.Elasticity:= _0_55;
-                gear^.Friction:= _0_03;
-                gear^.Density:= _2;
-                gear^.Timer:= 5000;
-                end;
-     gtCluster: begin
-                gear^.Radius:= 2;
-                gear^.Density:= _1_5;
-                gear^.RenderTimer:= true
-                end;
-      gtShover: gear^.Radius:= 20;
-       gtFlame: begin
-                gear^.Tag:= GetRandom(32);
-                gear^.Radius:= 1;
-                gear^.Health:= 5;
-                gear^.Density:= _1;
-                if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then
-                    begin
-                    gear^.dY:= (getrandom - _0_8) * _0_03;
-                    gear^.dX:= (getrandom - _0_5) * _0_4
-                    end
-                end;
-   gtFirePunch: begin
-                gear^.Radius:= 15;
-                gear^.Tag:= Y
-                end;
-     gtAirBomb: begin
-                gear^.Radius:= 5;
-                gear^.Density:= _2;
-                end;
-   gtBlowTorch: begin
-                gear^.Radius:= cHHRadius + cBlowTorchC;
-                gear^.Timer:= 7500
-                end;
-    gtSwitcher: begin
-                gear^.Z:= cCurrHHZ
-                end;
-      gtTarget: begin
-                gear^.ImpactSound:= sndGrenadeImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.Radius:= 10;
-                gear^.Elasticity:= _0_3;
-                gear^.Timer:= 0
-                end;
-      gtTardis: begin
-                gear^.Timer:= 0;
-                gear^.Pos:= 1;
-                gear^.Z:= cCurrHHZ+1;
-                end;
-      gtMortar: begin
-                gear^.Radius:= 4;
-                gear^.Elasticity:= _0_2;
-                gear^.Friction:= _0_08;
-                gear^.Density:= _1;
-                end;
-        gtWhip: gear^.Radius:= 20;
-      gtHammer: gear^.Radius:= 20;
-    gtKamikaze: begin
-                gear^.Health:= 2048;
-                gear^.Radius:= 20
-                end;
-        gtCake: begin
-                gear^.Health:= 2048;
-                gear^.Radius:= 7;
-                gear^.Z:= cOnHHZ;
-                gear^.RenderTimer:= true;
-                gear^.DirAngle:= -90 * hwSign(Gear^.dX);
-                if not dX.isNegative then
-                    gear^.Angle:= 1
-                else
-                    gear^.Angle:= 3
-                end;
- gtHellishBomb: begin
-                gear^.ImpactSound:= sndHellishImpact1;
-                gear^.nImpactSounds:= 4;
-                gear^.AdvBounce:= 1;
-                gear^.Radius:= 4;
-                gear^.Elasticity:= _0_5;
-                gear^.Friction:= _0_96;
-                gear^.Density:= _1_5;
-                gear^.RenderTimer:= true;
-                gear^.Timer:= 5000
-                end;
-       gtDrill: begin
-                if gear^.Timer = 0 then
-                    gear^.Timer:= 5000;
-                // Tag for drill strike. if 1 then first impact occured already
-                gear^.Tag := 0;
-                gear^.Radius:= 4;
-                gear^.Density:= _1;
-                end;
-        gtBall: begin
-                gear^.ImpactSound:= sndGrenadeImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.AdvBounce:= 1;
-                gear^.Radius:= 5;
-                gear^.Tag:= random(8);
-                gear^.Timer:= 5000;
-                gear^.Elasticity:= _0_7;
-                gear^.Friction:= _0_995;
-                gear^.Density:= _1_5;
-                end;
-     gtBallgun: begin
-                gear^.Timer:= 5001;
-                end;
-     gtRCPlane: begin
-                gear^.Timer:= 15000;
-                gear^.Health:= 3;
-                gear^.Radius:= 8
-                end;
-     gtJetpack: begin
-                gear^.Health:= 2000;
-                gear^.Damage:= 100
-                end;
-     gtMolotov: begin
-                gear^.Radius:= 6;
-                gear^.Density:= _2;
-                end;
-       gtBirdy: begin
-                gear^.Radius:= 16; // todo: check
-                gear^.Timer:= 0;
-                gear^.Health := 2000;
-                gear^.FlightTime := 2;
-                end;
-         gtEgg: begin
-                gear^.Radius:= 4;
-                gear^.Elasticity:= _0_6;
-                gear^.Friction:= _0_96;
-                gear^.Density:= _1;
-                if gear^.Timer = 0 then
-                    gear^.Timer:= 3000
-                end;
-      gtPortal: begin
-                gear^.ImpactSound:= sndMelonImpact;
-                gear^.nImpactSounds:= 1;
-                gear^.AdvBounce:= 0;
-                gear^.Radius:= 17;
-                // set color
-                gear^.Tag:= 2 * gear^.Timer;
-                gear^.Timer:= 15000;
-                gear^.RenderTimer:= false;
-                gear^.Health:= 100;
-                end;
-       gtPiano: begin
-                gear^.Radius:= 32;
-                gear^.Density:= _50;
-                end;
- gtSineGunShot: begin
-                gear^.Radius:= 5;
-                gear^.Health:= 6000;
-                end;
-gtFlamethrower: begin
-                gear^.Tag:= 10;
-                gear^.Timer:= 10;
-                gear^.Health:= 500;
-                gear^.Damage:= 100;
-                end;
-     gtLandGun: begin
-                gear^.Tag:= 10;
-                gear^.Timer:= 10;
-                gear^.Health:= 1000;
-                gear^.Damage:= 100;
-                end;
- gtPoisonCloud: begin
-                gear^.Timer:= 5000;
-                gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000;
-                end;
- gtResurrector: begin
-                gear^.Radius := 100;
-                gear^.Tag := 0
-                end;
-     gtWaterUp: begin
-                gear^.Tag := 47;
-                end;
-  gtNapalmBomb: begin
-                gear^.Timer:= 1000;
-                gear^.Radius:= 5;
-                gear^.Density:= _1_5;
-                end;
-   gtStructure: begin
-                gear^.Elasticity:= _0_55;
-                gear^.Friction:= _0_995;
-                gear^.Density:= _0_9;
-                gear^.Radius:= 13;
-                gear^.Health:= 200;
-                gear^.Timer:= 0;
-                gear^.Tag:= TotalRounds + 3;
-                gear^.Pos:= 1;
-                end;
-    end;
-
-InsertGearToList(gear);
-AddGear:= gear;
-
-ScriptCall('onGearAdd', gear^.uid);
-end;
-
-procedure DeleteGear(Gear: PGear);
-var team: PTeam;
-    t,i: Longword;
-    k: boolean;
-begin
-
-ScriptCall('onGearDelete', gear^.uid);
-
-DeleteCI(Gear);
-
-FreeTexture(Gear^.Tex);
-Gear^.Tex:= nil;
-
-// make sure that portals have their link removed before deletion
-if (Gear^.Kind = gtPortal) then
-    begin
-    if (Gear^.IntersectGear <> nil) then
-        if (Gear^.IntersectGear^.IntersectGear = Gear) then
-            Gear^.IntersectGear^.IntersectGear:= nil;
-    end
-else if Gear^.Kind = gtHedgehog then
-    (*
-    This behaviour dates back to revision 4, and I accidentally encountered it with TARDIS.  I don't think it must apply to any modern weapon, since if it was actually hit, the best the gear could do would be to destroy itself immediately, and you'd still end up with two graves.  I believe it should be removed
-     if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then
-        begin
-        AttackBar:= 0;
-        Gear^.Message:= gmDestroy;
-        CurAmmoGear^.Message:= gmDestroy;
-        exit
-        end
-    else*)
-        begin
-        if (hwRound(Gear^.Y) >= cWaterLine) then
-            begin
-            t:= max(Gear^.Damage, Gear^.Health);
-            Gear^.Damage:= t;
-            if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF)))
-            and (hwRound(Gear^.Y) < cWaterLine + 256) then
-                spawnHealthTagForHH(Gear, t);
-            end;
-
-        team:= Gear^.Hedgehog^.Team;
-        if CurrentHedgehog^.Gear = Gear then
-            begin
-            AttackBar:= 0;
-            FreeActionsList; // to avoid ThinkThread on drawned gear
-            if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0)
-            and (CurrentHedgehog^.MultiShootAttacks > 0) then
-                OnUsedAmmo(CurrentHedgehog^);
-            end;
-
-        Gear^.Hedgehog^.Gear:= nil;
-        if Gear^.Hedgehog^.King then
-            begin
-            // are there any other kings left? Just doing nil check.  Presumably a mortally wounded king will get reaped soon enough
-            k:= false;
-            for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
-                if (team^.Clan^.Teams[i]^.Hedgehogs[0].Gear <> nil) then
-                    k:= true;
-            if not k then
-                for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
-                    begin
-                    team^.Clan^.Teams[i]^.hasGone:= true;
-                    TeamGoneEffect(team^.Clan^.Teams[i]^)
-                    end
-            end;
-
-        // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog
-        // same stand for CheckHHDamage
-        if (Gear^.LastDamage <> nil) then
-            uStats.HedgehogDamaged(Gear, Gear^.LastDamage, 0, true)
-        else
-            uStats.HedgehogDamaged(Gear, CurrentHedgehog, 0, true);
-
-        inc(KilledHHs);
-        RecountTeamHealth(team);
-        if (CurrentHedgehog <> nil) and CurrentHedgehog^.Effects[heResurrectable] and
-        (not Gear^.Hedgehog^.Effects[heResurrectable]) then
-            with CurrentHedgehog^ do 
-                begin
-                inc(Team^.stats.AIKills);
-                FreeTexture(Team^.AIKillsTex);
-                Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
-                end
-        end;
-with Gear^ do
-    AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
-
-if CurAmmoGear = Gear then
-    CurAmmoGear:= nil;
-if FollowGear = Gear then
-    FollowGear:= nil;
-if lastGearByUID = Gear then
-    lastGearByUID := nil;
-RemoveGearFromList(Gear);
-Dispose(Gear)
-end;
-
-end.
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+unit uGearsList;
+
+interface
+uses uFloat, uTypes;
+
+function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
+procedure DeleteGear(Gear: PGear);
+procedure InsertGearToList(Gear: PGear);
+procedure RemoveGearFromList(Gear: PGear);
+
+implementation
+
+uses uRandom, uUtils, uConsts, uVariables, uAmmos, uTeams, uStats,
+    uTextures, uScript, uRenderUtils, uAI, uCollisions,
+    uGearsRender, uGearsUtils;
+
+procedure InsertGearToList(Gear: PGear);
+var tmp, ptmp: PGear;
+begin
+    tmp:= GearsList;
+    ptmp:= GearsList;
+    while (tmp <> nil) and (tmp^.Z <= Gear^.Z) do
+        begin
+        ptmp:= tmp;
+        tmp:= tmp^.NextGear
+        end;
+
+    if ptmp <> tmp then
+        begin
+        Gear^.NextGear:= ptmp^.NextGear;
+        Gear^.PrevGear:= ptmp;
+        if ptmp^.NextGear <> nil then
+            ptmp^.NextGear^.PrevGear:= Gear;
+        ptmp^.NextGear:= Gear
+        end
+    else
+        begin
+        Gear^.NextGear:= GearsList;
+        if Gear^.NextGear <> nil then
+            Gear^.NextGear^.PrevGear:= Gear;
+        GearsList:= Gear;
+        end;
+end;
+
+procedure RemoveGearFromList(Gear: PGear);
+begin
+if Gear^.NextGear <> nil then
+    Gear^.NextGear^.PrevGear:= Gear^.PrevGear;
+if Gear^.PrevGear <> nil then
+    Gear^.PrevGear^.NextGear:= Gear^.NextGear
+else
+    GearsList:= Gear^.NextGear
+end;
+    
+function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
+const Counter: Longword = 0;
+var gear: PGear;
+begin
+inc(Counter);
+AddFileLog('AddGear: #' + inttostr(Counter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
+
+New(gear);
+FillChar(gear^, sizeof(TGear), 0);
+gear^.X:= int2hwFloat(X);
+gear^.Y:= int2hwFloat(Y);
+gear^.Target.X:= NoPointX;
+gear^.Kind := Kind;
+gear^.State:= State;
+gear^.Active:= true;
+gear^.dX:= dX;
+gear^.dY:= dY;
+gear^.doStep:= doStepHandlers[Kind];
+gear^.CollisionIndex:= -1;
+gear^.Timer:= Timer;
+gear^.FlightTime:= 0;
+gear^.uid:= Counter;
+gear^.SoundChannel:= -1;
+gear^.ImpactSound:= sndNone;
+gear^.nImpactSounds:= 0;
+gear^.Density:= _1;
+// Define ammo association, if any.
+gear^.AmmoType:= GearKindAmmoTypeMap[Kind];
+if Ammoz[Gear^.AmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
+    gear^.Z:= cHHZ+1
+else gear^.Z:= cUsualZ;
+
+if CurrentHedgehog <> nil then
+    begin
+    gear^.Hedgehog:= CurrentHedgehog;
+    gear^.IntersectGear:= CurrentHedgehog^.Gear
+    end;
+    
+case Kind of
+     gtGrenade,
+     gtClusterBomb,
+     gtGasBomb: begin
+                gear^.ImpactSound:= sndGrenadeImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.AdvBounce:= 1;
+                gear^.Radius:= 5;
+                gear^.Elasticity:= _0_8;
+                gear^.Friction:= _0_8;
+                gear^.Density:= _1_5;
+                gear^.RenderTimer:= true;
+                if gear^.Timer = 0 then
+                    gear^.Timer:= 3000
+                end;
+  gtWatermelon: begin
+                gear^.ImpactSound:= sndMelonImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.AdvBounce:= 1;
+                gear^.Radius:= 6;
+                gear^.Elasticity:= _0_8;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _2;
+                gear^.RenderTimer:= true;
+                if gear^.Timer = 0 then
+                    gear^.Timer:= 3000
+                end;
+  gtMelonPiece: begin
+                gear^.Density:= _2;
+                end;
+    gtHedgehog: begin
+                gear^.AdvBounce:= 1;
+                gear^.Radius:= cHHRadius;
+                gear^.Elasticity:= _0_35;
+                gear^.Friction:= _0_999;
+                gear^.Angle:= cMaxAngle div 2;
+                gear^.Density:= _3;
+                gear^.Z:= cHHZ;
+                if (GameFlags and gfAISurvival) <> 0 then
+                    if gear^.Hedgehog^.BotLevel > 0 then
+                        gear^.Hedgehog^.Effects[heResurrectable] := true;
+                end;
+       gtShell: begin
+                gear^.Radius:= 4;
+                gear^.Density:= _1;
+                end;
+       gtSnowball: begin
+                gear^.ImpactSound:= sndMudballImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Radius:= 4;
+                gear^.Elasticity:= _1;
+                gear^.Friction:= _1;
+                gear^.Density:= _0_5;
+                end;
+
+     gtFlake: begin
+                with Gear^ do
+                    begin
+                    Pos:= 0;
+                    Radius:= 1;
+                    DirAngle:= random * 360;
+                    if State and gstTmpFlag = 0 then
+                        begin
+                        dx.isNegative:= GetRandom(2) = 0;
+                        dx.QWordValue:= GetRandom(100000000);
+                        dy.isNegative:= false;
+                        dy.QWordValue:= GetRandom(70000000);
+                        if GetRandom(2) = 0 then
+                            dx := -dx
+                        end;
+                    State:= State or gstInvisible;
+                    Health:= random(vobFrameTicks);
+                    Timer:= random(vobFramesCount);
+                    Angle:= (random(2) * 2 - 1) * (1 + random(10000)) * vobVelocity
+                    end
+                end;
+       gtGrave: begin
+                gear^.ImpactSound:= sndGraveImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Radius:= 10;
+                gear^.Elasticity:= _0_6;
+                end;
+         gtBee: begin
+                gear^.Radius:= 5;
+                gear^.Timer:= 500;
+                gear^.RenderTimer:= true;
+                gear^.Elasticity:= _0_9;
+                gear^.Tag:= 0;
+                end;
+   gtSeduction: begin
+                gear^.Radius:= 250;
+                end;
+ gtShotgunShot: begin
+                gear^.Timer:= 900;
+                gear^.Radius:= 2
+                end;
+  gtPickHammer: begin
+                gear^.Radius:= 10;
+                gear^.Timer:= 4000
+                end;
+   gtHammerHit: begin
+                gear^.Radius:= 8;
+                gear^.Timer:= 125
+                end;
+        gtRope: begin
+                gear^.Radius:= 3;
+                gear^.Friction:= _450 * _0_01 * cRopePercent;
+                RopePoints.Count:= 0;
+                end;
+        gtMine: begin
+                gear^.ImpactSound:= sndMineImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Health:= 10;
+                gear^.State:= gear^.State or gstMoving;
+                gear^.Radius:= 2;
+                gear^.Elasticity:= _0_55;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _0_9;
+                if cMinesTime < 0 then
+                    gear^.Timer:= getrandom(51)*100
+                else
+                    gear^.Timer:= cMinesTime;
+                end;
+       gtSMine: begin
+                gear^.Health:= 10;
+                gear^.State:= gear^.State or gstMoving;
+                gear^.Radius:= 2;
+                gear^.Elasticity:= _0_55;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _0_9;
+                gear^.Timer:= 500;
+                end;
+        gtCase: begin
+                gear^.ImpactSound:= sndGraveImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Radius:= 16;
+                gear^.Elasticity:= _0_3
+                end;
+  gtExplosives: begin
+                gear^.ImpactSound:= sndGrenadeImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Radius:= 16;
+                gear^.Elasticity:= _0_4;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _6;
+                gear^.Health:= cBarrelHealth;
+                gear^.Z:= cHHZ-1
+                end;
+  gtDEagleShot: begin
+                gear^.Radius:= 1;
+                gear^.Health:= 50
+                end;
+  gtSniperRifleShot: begin
+                gear^.Radius:= 1;
+                gear^.Health:= 50
+                end;
+    gtDynamite: begin
+                gear^.Radius:= 3;
+                gear^.Elasticity:= _0_55;
+                gear^.Friction:= _0_03;
+                gear^.Density:= _2;
+                gear^.Timer:= 5000;
+                end;
+     gtCluster: begin
+                gear^.Radius:= 2;
+                gear^.Density:= _1_5;
+                gear^.RenderTimer:= true
+                end;
+      gtShover: gear^.Radius:= 20;
+       gtFlame: begin
+                gear^.Tag:= GetRandom(32);
+                gear^.Radius:= 1;
+                gear^.Health:= 5;
+                gear^.Density:= _1;
+                if (gear^.dY.QWordValue = 0) and (gear^.dX.QWordValue = 0) then
+                    begin
+                    gear^.dY:= (getrandom - _0_8) * _0_03;
+                    gear^.dX:= (getrandom - _0_5) * _0_4
+                    end
+                end;
+   gtFirePunch: begin
+                gear^.Radius:= 15;
+                gear^.Tag:= Y
+                end;
+     gtAirBomb: begin
+                gear^.Radius:= 5;
+                gear^.Density:= _2;
+                end;
+   gtBlowTorch: begin
+                gear^.Radius:= cHHRadius + cBlowTorchC;
+                gear^.Timer:= 7500
+                end;
+    gtSwitcher: begin
+                gear^.Z:= cCurrHHZ
+                end;
+      gtTarget: begin
+                gear^.ImpactSound:= sndGrenadeImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Radius:= 10;
+                gear^.Elasticity:= _0_3;
+                gear^.Timer:= 0
+                end;
+      gtTardis: begin
+                gear^.Timer:= 0;
+                gear^.Pos:= 1;
+                gear^.Z:= cCurrHHZ+1;
+                end;
+      gtMortar: begin
+                gear^.Radius:= 4;
+                gear^.Elasticity:= _0_2;
+                gear^.Friction:= _0_08;
+                gear^.Density:= _1;
+                end;
+        gtWhip: gear^.Radius:= 20;
+      gtHammer: gear^.Radius:= 20;
+    gtKamikaze: begin
+                gear^.Health:= 2048;
+                gear^.Radius:= 20
+                end;
+        gtCake: begin
+                gear^.Health:= 2048;
+                gear^.Radius:= 7;
+                gear^.Z:= cOnHHZ;
+                gear^.RenderTimer:= true;
+                gear^.DirAngle:= -90 * hwSign(Gear^.dX);
+                if not dX.isNegative then
+                    gear^.Angle:= 1
+                else
+                    gear^.Angle:= 3
+                end;
+ gtHellishBomb: begin
+                gear^.ImpactSound:= sndHellishImpact1;
+                gear^.nImpactSounds:= 4;
+                gear^.AdvBounce:= 1;
+                gear^.Radius:= 4;
+                gear^.Elasticity:= _0_5;
+                gear^.Friction:= _0_96;
+                gear^.Density:= _1_5;
+                gear^.RenderTimer:= true;
+                gear^.Timer:= 5000
+                end;
+       gtDrill: begin
+                if gear^.Timer = 0 then
+                    gear^.Timer:= 5000;
+                // Tag for drill strike. if 1 then first impact occured already
+                gear^.Tag := 0;
+                gear^.Radius:= 4;
+                gear^.Density:= _1;
+                end;
+        gtBall: begin
+                gear^.ImpactSound:= sndGrenadeImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.AdvBounce:= 1;
+                gear^.Radius:= 5;
+                gear^.Tag:= random(8);
+                gear^.Timer:= 5000;
+                gear^.Elasticity:= _0_7;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _1_5;
+                end;
+     gtBallgun: begin
+                gear^.Timer:= 5001;
+                end;
+     gtRCPlane: begin
+                gear^.Timer:= 15000;
+                gear^.Health:= 3;
+                gear^.Radius:= 8
+                end;
+     gtJetpack: begin
+                gear^.Health:= 2000;
+                gear^.Damage:= 100
+                end;
+     gtMolotov: begin
+                gear^.Radius:= 6;
+                gear^.Density:= _2;
+                end;
+       gtBirdy: begin
+                gear^.Radius:= 16; // todo: check
+                gear^.Timer:= 0;
+                gear^.Health := 2000;
+                gear^.FlightTime := 2;
+                end;
+         gtEgg: begin
+                gear^.Radius:= 4;
+                gear^.Elasticity:= _0_6;
+                gear^.Friction:= _0_96;
+                gear^.Density:= _1;
+                if gear^.Timer = 0 then
+                    gear^.Timer:= 3000
+                end;
+      gtPortal: begin
+                gear^.ImpactSound:= sndMelonImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.AdvBounce:= 0;
+                gear^.Radius:= 17;
+                // set color
+                gear^.Tag:= 2 * gear^.Timer;
+                gear^.Timer:= 15000;
+                gear^.RenderTimer:= false;
+                gear^.Health:= 100;
+                end;
+       gtPiano: begin
+                gear^.Radius:= 32;
+                gear^.Density:= _50;
+                end;
+ gtSineGunShot: begin
+                gear^.Radius:= 5;
+                gear^.Health:= 6000;
+                end;
+gtFlamethrower: begin
+                gear^.Tag:= 10;
+                gear^.Timer:= 10;
+                gear^.Health:= 500;
+                gear^.Damage:= 100;
+                end;
+     gtLandGun: begin
+                gear^.Tag:= 10;
+                gear^.Timer:= 10;
+                gear^.Health:= 1000;
+                gear^.Damage:= 100;
+                end;
+ gtPoisonCloud: begin
+                gear^.Timer:= 5000;
+                gear^.dY:= int2hwfloat(-4 + longint(getRandom(8))) / 1000;
+                end;
+ gtResurrector: begin
+                gear^.Radius := 100;
+                gear^.Tag := 0
+                end;
+     gtWaterUp: begin
+                gear^.Tag := 47;
+                end;
+  gtNapalmBomb: begin
+                gear^.Timer:= 1000;
+                gear^.Radius:= 5;
+                gear^.Density:= _1_5;
+                end;
+   gtStructure: begin
+                gear^.Elasticity:= _0_55;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _0_9;
+                gear^.Radius:= 13;
+                gear^.Health:= 200;
+                gear^.Timer:= 0;
+                gear^.Tag:= TotalRounds + 3;
+                gear^.Pos:= 1;
+                end;
+    end;
+
+InsertGearToList(gear);
+AddGear:= gear;
+
+ScriptCall('onGearAdd', gear^.uid);
+end;
+
+procedure DeleteGear(Gear: PGear);
+var team: PTeam;
+    t,i: Longword;
+    k: boolean;
+begin
+
+ScriptCall('onGearDelete', gear^.uid);
+
+DeleteCI(Gear);
+
+FreeTexture(Gear^.Tex);
+Gear^.Tex:= nil;
+
+// make sure that portals have their link removed before deletion
+if (Gear^.Kind = gtPortal) then
+    begin
+    if (Gear^.IntersectGear <> nil) then
+        if (Gear^.IntersectGear^.IntersectGear = Gear) then
+            Gear^.IntersectGear^.IntersectGear:= nil;
+    end
+else if Gear^.Kind = gtHedgehog then
+    (*
+    This behaviour dates back to revision 4, and I accidentally encountered it with TARDIS.  I don't think it must apply to any modern weapon, since if it was actually hit, the best the gear could do would be to destroy itself immediately, and you'd still end up with two graves.  I believe it should be removed
+     if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then
+        begin
+        AttackBar:= 0;
+        Gear^.Message:= gmDestroy;
+        CurAmmoGear^.Message:= gmDestroy;
+        exit
+        end
+    else*)
+        begin
+        if (hwRound(Gear^.Y) >= cWaterLine) then
+            begin
+            t:= max(Gear^.Damage, Gear^.Health);
+            Gear^.Damage:= t;
+            if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cWaterOpacity < $FF)))
+            and (hwRound(Gear^.Y) < cWaterLine + 256) then
+                spawnHealthTagForHH(Gear, t);
+            end;
+
+        team:= Gear^.Hedgehog^.Team;
+        if CurrentHedgehog^.Gear = Gear then
+            begin
+            AttackBar:= 0;
+            FreeActionsList; // to avoid ThinkThread on drawned gear
+            if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0)
+            and (CurrentHedgehog^.MultiShootAttacks > 0) then
+                OnUsedAmmo(CurrentHedgehog^);
+            end;
+
+        Gear^.Hedgehog^.Gear:= nil;
+        if Gear^.Hedgehog^.King then
+            begin
+            // are there any other kings left? Just doing nil check.  Presumably a mortally wounded king will get reaped soon enough
+            k:= false;
+            for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
+                if (team^.Clan^.Teams[i]^.Hedgehogs[0].Gear <> nil) then
+                    k:= true;
+            if not k then
+                for i:= 0 to Pred(team^.Clan^.TeamsNumber) do
+                    begin
+                    team^.Clan^.Teams[i]^.hasGone:= true;
+                    TeamGoneEffect(team^.Clan^.Teams[i]^)
+                    end
+            end;
+
+        // should be not CurrentHedgehog, but hedgehog of the last gear which caused damage to this hog
+        // same stand for CheckHHDamage
+        if (Gear^.LastDamage <> nil) then
+            uStats.HedgehogDamaged(Gear, Gear^.LastDamage, 0, true)
+        else
+            uStats.HedgehogDamaged(Gear, CurrentHedgehog, 0, true);
+
+        inc(KilledHHs);
+        RecountTeamHealth(team);
+        if (CurrentHedgehog <> nil) and CurrentHedgehog^.Effects[heResurrectable] and
+        (not Gear^.Hedgehog^.Effects[heResurrectable]) then
+            with CurrentHedgehog^ do 
+                begin
+                inc(Team^.stats.AIKills);
+                FreeTexture(Team^.AIKillsTex);
+                Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
+                end
+        end;
+with Gear^ do
+    AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
+
+if CurAmmoGear = Gear then
+    CurAmmoGear:= nil;
+if FollowGear = Gear then
+    FollowGear:= nil;
+if lastGearByUID = Gear then
+    lastGearByUID := nil;
+RemoveGearFromList(Gear);
+Dispose(Gear)
+end;
+
+end.
--- a/hedgewars/uGearsUtils.pas	Tue Jan 17 09:01:31 2012 -0500
+++ b/hedgewars/uGearsUtils.pas	Tue Jan 17 09:20:16 2012 -0500
@@ -1,573 +1,573 @@
-(*
- * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *)
-
-{$INCLUDE "options.inc"}
-
-unit uGearsUtils;
-interface
-uses uTypes;
-
-procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord = $FFFFFFFF); 
-function  ModifyDamage(dmg: Longword; Gear: PGear): Longword;
-procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
-procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
-procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
-procedure CheckHHDamage(Gear: PGear);
-procedure CalcRotationDirAngle(Gear: PGear);
-procedure ResurrectHedgehog(gear: PGear);
-procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean = false);
-function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
-function  CheckGearsNear(mX, mY: LongInt; Kind: TGearsType; rX, rY: LongInt): PGear;
-function  CheckGearDrowning(Gear: PGear): boolean;
-
-var doStepHandlers: array[TGearType] of TGearStepProcedure;
-
-
-implementation
-uses uFloat, uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc,
-    uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore,
-    uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, uGears,
-    uGearsList;
-
-procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord);
-var Gear: PGear;
-    dmg, dmgRadius, dmgBase: LongInt;
-    fX, fY: hwFloat;
-    vg: PVisualGear;
-    i, cnt: LongInt;
-begin
-if Radius > 4 then AddFileLog('Explosion: at (' + inttostr(x) + ',' + inttostr(y) + ')');
-if Radius > 25 then KickFlakes(Radius, X, Y);
-
-if ((Mask and EXPLNoGfx) = 0) then
-    begin
-    vg:= nil;
-    if Radius > 50 then vg:= AddVisualGear(X, Y, vgtBigExplosion)
-    else if Radius > 10 then vg:= AddVisualGear(X, Y, vgtExplosion);
-    if vg <> nil then
-        vg^.Tint:= Tint;
-    end;
-if (Mask and EXPLAutoSound) <> 0 then PlaySound(sndExplosion);
-
-if (Mask and EXPLAllDamageInRadius) = 0 then
-    dmgRadius:= Radius shl 1
-else
-    dmgRadius:= Radius;
-dmgBase:= dmgRadius + cHHRadius div 2;
-fX:= int2hwFloat(X);
-fY:= int2hwFloat(Y);
-Gear:= GearsList;
-while Gear <> nil do
-    begin
-    dmg:= 0;
-    //dmg:= dmgRadius  + cHHRadius div 2 - hwRound(Distance(Gear^.X - int2hwFloat(X), Gear^.Y - int2hwFloat(Y)));
-    //if (dmg > 1) and
-    if (Gear^.State and gstNoDamage) = 0 then
-        begin
-        case Gear^.Kind of
-            gtHedgehog,
-                gtMine,
-                gtBall,
-                gtMelonPiece,
-                gtGrenade,
-                gtClusterBomb,
-            //    gtCluster, too game breaking I think
-                gtSMine,
-                gtCase,
-                gtTarget,
-                gtFlame,
-                gtExplosives,
-                gtStructure: begin
-// Run the calcs only once we know we have a type that will need damage
-                        if hwRound(hwAbs(Gear^.X-fX)+hwAbs(Gear^.Y-fY)) < dmgBase then
-                            dmg:= dmgBase - max(hwRound(Distance(Gear^.X - fX, Gear^.Y - fY)),Gear^.Radius);
-                        if dmg > 1 then
-                            begin
-                            dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
-                            //AddFileLog('Damage: ' + inttostr(dmg));
-                            if (Mask and EXPLNoDamage) = 0 then
-                                begin
-                                if not Gear^.Invulnerable then
-                                    ApplyDamage(Gear, AttackingHog, dmg, dsExplosion)
-                                else
-                                    Gear^.State:= Gear^.State or gstWinner;
-                                end;
-                            if ((Mask and EXPLDoNotTouchAny) = 0) and (((Mask and EXPLDoNotTouchHH) = 0) or (Gear^.Kind <> gtHedgehog)) then
-                                begin
-                                DeleteCI(Gear);
-                                Gear^.dX:= Gear^.dX + SignAs(_0_005 * dmg + cHHKick, Gear^.X - fX)/(Gear^.Density/_3);
-                                Gear^.dY:= Gear^.dY + SignAs(_0_005 * dmg + cHHKick, Gear^.Y - fY)/(Gear^.Density/_3);
-
-                                Gear^.State:= (Gear^.State or gstMoving) and (not gstLoser);
-                                if not Gear^.Invulnerable then
-                                    Gear^.State:= (Gear^.State or gstMoving) and (not gstWinner);
-                                Gear^.Active:= true;
-                                if Gear^.Kind <> gtFlame then FollowGear:= Gear
-                                end;
-                            if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) and (not Gear^.Invulnerable) then
-                                Gear^.Hedgehog^.Effects[hePoisoned] := true;
-                            end;
-
-                        end;
-                gtGrave: begin
-// Run the calcs only once we know we have a type that will need damage
-                        if hwRound(hwAbs(Gear^.X-fX)+hwAbs(Gear^.Y-fY)) < dmgBase then
-                            dmg:= dmgBase - hwRound(Distance(Gear^.X - fX, Gear^.Y - fY));
-                        if dmg > 1 then
-                            begin
-                            dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
-                            Gear^.dY:= - _0_004 * dmg;
-                            Gear^.Active:= true
-                            end
-                        end;
-            end;
-        end;
-    Gear:= Gear^.NextGear
-    end;
-
-if (Mask and EXPLDontDraw) = 0 then
-    if (GameFlags and gfSolidLand) = 0 then
-        begin
-        cnt:= DrawExplosion(X, Y, Radius) div 1608; // approx 2 16x16 circles to erase per chunk
-        if (cnt > 0) and (SpritesData[sprChunk].Texture <> nil) then
-            for i:= 0 to cnt do
-                AddVisualGear(X, Y, vgtChunk)
-        end;
-
-uAIMisc.AwareOfExplosion(0, 0, 0)
-end;
-
-function ModifyDamage(dmg: Longword; Gear: PGear): Longword;
-var i: hwFloat;
-begin
-(* Invulnerability cannot be placed in here due to still needing kicks
-   Not without a new damage machine.
-   King check should be in here instead of ApplyDamage since Tiy wants them kicked less
-*)
-i:= _1;
-if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then
-    i:= _1_5;
-if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.King) then
-    ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent * _0_5)
-else
-    ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent)
-end;
-
-procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
-var s: shortstring;
-    vampDmg, tmpDmg, i: Longword;
-    vg: PVisualGear;
-begin
-    if Damage = 0 then
-        exit; // nothing to apply
-
-    if (Gear^.Kind = gtHedgehog) then
-        begin
-        Gear^.LastDamage := AttackerHog;
-
-        Gear^.Hedgehog^.Team^.Clan^.Flawless:= false;
-        HHHurt(Gear^.Hedgehog, Source);
-        AddDamageTag(hwRound(Gear^.X), hwRound(Gear^.Y), Damage, Gear^.Hedgehog^.Team^.Clan^.Color);
-        tmpDmg:= min(Damage, max(0,Gear^.Health-Gear^.Damage));
-        if (Gear <> CurrentHedgehog^.Gear) and (CurrentHedgehog^.Gear <> nil) and (tmpDmg >= 1) then
-            begin
-            if cVampiric then
-                begin
-                vampDmg:= hwRound(int2hwFloat(tmpDmg)*_0_8);
-                if vampDmg >= 1 then
-                    begin
-                    // was considering pulsing on attack, Tiy thinks it should be permanent while in play
-                    //CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstVampiric;
-                    inc(CurrentHedgehog^.Gear^.Health,vampDmg);
-                    str(vampDmg, s);
-                    s:= '+' + s;
-                    AddCaption(s, CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
-                    RenderHealth(CurrentHedgehog^);
-                    RecountTeamHealth(CurrentHedgehog^.Team);
-                    i:= 0;
-                    while i < vampDmg do
-                        begin
-                        vg:= AddVisualGear(hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y), vgtStraightShot);
-                        if vg <> nil then
-                            with vg^ do
-                                begin
-                                Tint:= $FF0000FF;
-                                State:= ord(sprHealth)
-                                end;
-                        inc(i, 5);
-                        end;
-                    end
-                end;
-        if ((GameFlags and gfKarma) <> 0) and 
-        ((GameFlags and gfInvulnerable) = 0)
-        and (not CurrentHedgehog^.Gear^.Invulnerable) then
-            begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid
-            inc(CurrentHedgehog^.Gear^.Karma, tmpDmg);
-            CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog;
-            spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
-            end;
-        uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false);    
-        end;
-    end
-    else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure
-        begin
-        Gear^.Hedgehog:= AttackerHog;
-        end;
-    inc(Gear^.Damage, Damage);
-    
-    ScriptCall('onGearDamage', Gear^.UID, Damage);
-end;
-
-procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
-var tag: PVisualGear;
-begin
-tag:= AddVisualGear(hwRound(HHGear^.X), hwRound(HHGear^.Y), vgtHealthTag, dmg);
-if (tag <> nil) then
-    tag^.Hedgehog:= HHGear^.Hedgehog; // the tag needs the tag to determine the text color
-AllInactive:= false;
-HHGear^.Active:= true;
-end;
-    
-procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
-begin
-if (Source = dsFall) or (Source = dsExplosion) then
-    case random(3) of
-        0: PlaySound(sndOoff1, Hedgehog^.Team^.voicepack);
-        1: PlaySound(sndOoff2, Hedgehog^.Team^.voicepack);
-        2: PlaySound(sndOoff3, Hedgehog^.Team^.voicepack);
-    end
-else if (Source = dsPoison) then
-    case random(2) of
-        0: PlaySound(sndPoisonCough, Hedgehog^.Team^.voicepack);
-        1: PlaySound(sndPoisonMoan, Hedgehog^.Team^.voicepack);
-    end
-else
-    case random(4) of
-        0: PlaySound(sndOw1, Hedgehog^.Team^.voicepack);
-        1: PlaySound(sndOw2, Hedgehog^.Team^.voicepack);
-        2: PlaySound(sndOw3, Hedgehog^.Team^.voicepack);
-        3: PlaySound(sndOw4, Hedgehog^.Team^.voicepack);
-    end
-end;
-
-procedure CheckHHDamage(Gear: PGear);
-var 
-    dmg: Longword;
-    i: LongInt;
-    particle: PVisualGear;
-begin
-    if _0_4 < Gear^.dY then
-        begin
-        dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
-        PlaySound(sndBump);
-        if dmg < 1 then
-            exit;
-
-        for i:= min(12, (3 + dmg div 10)) downto 0 do
-            begin
-            particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
-            if particle <> nil then
-                particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
-            end;
-
-        if (Gear^.Invulnerable) then
-            exit;
-
-        //if _0_6 < Gear^.dY then
-        //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
-        //else
-        //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
-
-        if Gear^.LastDamage <> nil then
-            ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
-        else
-            ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
-    end
-end;
-
-
-procedure CalcRotationDirAngle(Gear: PGear);
-var 
-    dAngle: real;
-begin
-    dAngle := (Gear^.dX.QWordValue + Gear^.dY.QWordValue) / $80000000;
-    if not Gear^.dX.isNegative then
-        Gear^.DirAngle := Gear^.DirAngle + dAngle
-    else
-        Gear^.DirAngle := Gear^.DirAngle - dAngle;
-
-    if Gear^.DirAngle < 0 then
-        Gear^.DirAngle := Gear^.DirAngle + 360
-    else if 360 < Gear^.DirAngle then
-        Gear^.DirAngle := Gear^.DirAngle - 360
-end;
-
-function CheckGearDrowning(Gear: PGear): boolean;
-var 
-    skipSpeed, skipAngle, skipDecay: hwFloat;
-    i, maxDrops, X, Y: LongInt;
-    vdX, vdY: real;
-    particle: PVisualGear;
-    isSubmersible: boolean;
-begin
-    // probably needs tweaking. might need to be in a case statement based upon gear type
-    Y:= hwRound(Gear^.Y);
-    if cWaterLine < Y + Gear^.Radius then
-        begin
-        isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
-        skipSpeed := _0_25;
-        skipAngle := _1_9;
-        skipDecay := _0_87;
-        X:= hwRound(Gear^.X);
-        vdX:= hwFloat2Float(Gear^.dX);
-        vdY:= hwFloat2Float(Gear^.dY);
-        // this could perhaps be a tiny bit higher.
-        if  (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed)
-        and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
-            begin
-            Gear^.dY.isNegative := true;
-            Gear^.dY := Gear^.dY * skipDecay;
-            Gear^.dX := Gear^.dX * skipDecay;
-            CheckGearDrowning := false;
-            PlaySound(sndSkip)
-            end
-        else
-            begin
-            if not isSubmersible then
-                begin
-                CheckGearDrowning := true;
-                Gear^.State := gstDrowning;
-                Gear^.RenderTimer := false;
-                if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot)
-                and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
-                    if Gear^.Kind = gtHedgehog then
-                        begin
-                        if Gear^.Hedgehog^.Effects[heResurrectable] then
-                            ResurrectHedgehog(Gear)
-                        else
-                            begin
-                            Gear^.doStep := @doStepDrowningGear;
-                            Gear^.State := Gear^.State and (not gstHHDriven);
-                            AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
-                            end
-                        end
-                    else
-                        Gear^.doStep := @doStepDrowningGear;
-                        if Gear^.Kind = gtFlake then
-                            exit // skip splashes 
-                end;
-            if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
-            or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
-            and (CurAmmoGear^.dY < _0_01))) then
-                // don't play splash if they are already way past the surface
-                PlaySound(sndSplash)
-            end;
-
-        if ((cReducedQuality and rqPlainSplash) = 0)
-        and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
-        or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
-        and (CurAmmoGear^.dY < _0_01)))) then
-            begin
-            AddVisualGear(X, cWaterLine, vgtSplash);
-
-            maxDrops := (Gear^.Radius div 2) + round(vdX * Gear^.Radius * 2) + round(vdY * Gear^.Radius * 2);
-            for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do
-                begin
-                particle := AddVisualGear(X - 3 + Random(6), cWaterLine, vgtDroplet);
-                if particle <> nil then
-                    begin
-                    particle^.dX := particle^.dX - vdX / 10;
-                    particle^.dY := particle^.dY - vdY / 5;
-                    end
-                end
-            end;
-        if isSubmersible and (CurAmmoGear^.Pos = 0) then
-            CurAmmoGear^.Pos := 1000
-        end
-    else
-        CheckGearDrowning := false;
-end;
-
-
-procedure ResurrectHedgehog(gear: PGear);
-var tempTeam : PTeam;
-begin
-    AttackBar:= 0;
-    gear^.dX := _0;
-    gear^.dY := _0;
-    gear^.Damage := 0;
-    gear^.Health := gear^.Hedgehog^.InitialHealth;
-    gear^.Hedgehog^.Effects[hePoisoned] := false;
-    if not CurrentHedgehog^.Effects[heResurrectable] then
-        with CurrentHedgehog^ do 
-            begin
-            inc(Team^.stats.AIKills);
-            FreeTexture(Team^.AIKillsTex);
-            Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
-            end;
-    tempTeam := gear^.Hedgehog^.Team;
-    DeleteCI(gear);
-    FindPlace(gear, false, 0, LAND_WIDTH, true); 
-    if gear <> nil then
-        begin
-        RenderHealth(gear^.Hedgehog^);
-        ScriptCall('onGearResurrect', gear^.uid);
-        gear^.State := gstWait;
-    end;
-    RecountTeamHealth(tempTeam);
-end;
-
-function CountNonZeroz(x, y, r, c: LongInt): LongInt;
-var i: LongInt;
-    count: LongInt = 0;
-begin
-if (y and LAND_HEIGHT_MASK) = 0 then
-    for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do
-        if Land[y, i] <> 0 then
-            begin
-            inc(count);
-            if count = c then
-                exit(count)
-            end;
-CountNonZeroz:= count;
-end;
-
-procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
-var x: LongInt;
-    y, sy: LongInt;
-    ar: array[0..511] of TPoint;
-    ar2: array[0..1023] of TPoint;
-    cnt, cnt2: Longword;
-    delta: LongInt;
-    reallySkip, tryAgain: boolean;
-begin
-reallySkip:= false; // try not skipping proximity at first
-tryAgain:= true;
-while tryAgain do
-    begin
-    delta:= 250;
-    cnt2:= 0;
-    repeat
-        x:= Left + LongInt(GetRandom(Delta));
-        repeat
-            inc(x, Delta);
-            cnt:= 0;
-            y:= min(1024, topY) - 2 * Gear^.Radius;
-            while y < cWaterLine do
-                begin
-                repeat
-                    inc(y, 2);
-                until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) = 0);
-
-                sy:= y;
-
-                repeat
-                    inc(y);
-                until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
-
-                if (y - sy > Gear^.Radius * 2)
-                    and (((Gear^.Kind = gtExplosives)
-                    and (y < cWaterLine)
-                    and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil))
-                    and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
-                or
-                    ((Gear^.Kind <> gtExplosives)
-                    and (y < cWaterLine)
-                    and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil)))) then
-                 
-                          begin
-                    ar[cnt].X:= x;
-                    if withFall then
-                        ar[cnt].Y:= sy + Gear^.Radius
-                    else
-                        ar[cnt].Y:= y - Gear^.Radius;
-                    inc(cnt)
-                    end;
-
-                inc(y, 45)
-                end;
-
-            if cnt > 0 then
-                with ar[GetRandom(cnt)] do
-                    begin
-                    ar2[cnt2].x:= x;
-                    ar2[cnt2].y:= y;
-                    inc(cnt2)
-                    end
-        until (x + Delta > Right);
-
-        dec(Delta, 60)
-    until (cnt2 > 0) or (Delta < 70);
-    if (cnt2 = 0) and skipProximity and (not reallySkip) then
-        tryAgain:= true
-    else tryAgain:= false;
-    reallySkip:= true;
-    end;
-
-if cnt2 > 0 then
-    with ar2[GetRandom(cnt2)] do
-        begin
-        Gear^.X:= int2hwFloat(x);
-        Gear^.Y:= int2hwFloat(y);
-        AddFileLog('Assigned Gear coordinates (' + inttostr(x) + ',' + inttostr(y) + ')');
-        end
-    else
-    begin
-    OutError('Can''t find place for Gear', false);
-    if Gear^.Kind = gtHedgehog then
-        Gear^.Hedgehog^.Effects[heResurrectable] := false;
-    DeleteGear(Gear);
-    Gear:= nil
-    end
-end;
-
-function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
-var t: PGear;
-begin
-t:= GearsList;
-rX:= sqr(rX);
-rY:= sqr(rY);
-
-while t <> nil do
-    begin
-    if (t <> Gear) and (t^.Kind = Kind) then
-        if not((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1) then
-        exit(t);
-    t:= t^.NextGear
-    end;
-
-CheckGearNear:= nil
-end;
-
-
-function CheckGearsNear(mX, mY: LongInt; Kind: TGearsType; rX, rY: LongInt): PGear;
-var t: PGear;
-begin
-t:= GearsList;
-rX:= sqr(rX);
-rY:= sqr(rY);
-while t <> nil do
-    begin
-    if t^.Kind in Kind then
-        if not (hwSqr(int2hwFloat(mX) - t^.X) / rX + hwSqr(int2hwFloat(mY) - t^.Y) / rY > _1) then
-            exit(t);
-    t:= t^.NextGear
-    end;
-CheckGearsNear:= nil
-end;
-end.
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2011 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit uGearsUtils;
+interface
+uses uTypes;
+
+procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord = $FFFFFFFF); 
+function  ModifyDamage(dmg: Longword; Gear: PGear): Longword;
+procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
+procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
+procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
+procedure CheckHHDamage(Gear: PGear);
+procedure CalcRotationDirAngle(Gear: PGear);
+procedure ResurrectHedgehog(gear: PGear);
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean = false);
+function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
+function  CheckGearsNear(mX, mY: LongInt; Kind: TGearsType; rX, rY: LongInt): PGear;
+function  CheckGearDrowning(Gear: PGear): boolean;
+
+var doStepHandlers: array[TGearType] of TGearStepProcedure;
+
+
+implementation
+uses uFloat, uSound, uCollisions, uUtils, uConsts, uVisualGears, uAIMisc,
+    uVariables, uLandGraphics, uScript, uStats, uCaptions, uTeams, uStore,
+    uLocale, uTextures, uRenderUtils, uRandom, SDLh, uDebug, uGears,
+    uGearsList;
+
+procedure doMakeExplosion(X, Y, Radius: LongInt; AttackingHog: PHedgehog; Mask: Longword; const Tint: LongWord);
+var Gear: PGear;
+    dmg, dmgRadius, dmgBase: LongInt;
+    fX, fY: hwFloat;
+    vg: PVisualGear;
+    i, cnt: LongInt;
+begin
+if Radius > 4 then AddFileLog('Explosion: at (' + inttostr(x) + ',' + inttostr(y) + ')');
+if Radius > 25 then KickFlakes(Radius, X, Y);
+
+if ((Mask and EXPLNoGfx) = 0) then
+    begin
+    vg:= nil;
+    if Radius > 50 then vg:= AddVisualGear(X, Y, vgtBigExplosion)
+    else if Radius > 10 then vg:= AddVisualGear(X, Y, vgtExplosion);
+    if vg <> nil then
+        vg^.Tint:= Tint;
+    end;
+if (Mask and EXPLAutoSound) <> 0 then PlaySound(sndExplosion);
+
+if (Mask and EXPLAllDamageInRadius) = 0 then
+    dmgRadius:= Radius shl 1
+else
+    dmgRadius:= Radius;
+dmgBase:= dmgRadius + cHHRadius div 2;
+fX:= int2hwFloat(X);
+fY:= int2hwFloat(Y);
+Gear:= GearsList;
+while Gear <> nil do
+    begin
+    dmg:= 0;
+    //dmg:= dmgRadius  + cHHRadius div 2 - hwRound(Distance(Gear^.X - int2hwFloat(X), Gear^.Y - int2hwFloat(Y)));
+    //if (dmg > 1) and
+    if (Gear^.State and gstNoDamage) = 0 then
+        begin
+        case Gear^.Kind of
+            gtHedgehog,
+                gtMine,
+                gtBall,
+                gtMelonPiece,
+                gtGrenade,
+                gtClusterBomb,
+            //    gtCluster, too game breaking I think
+                gtSMine,
+                gtCase,
+                gtTarget,
+                gtFlame,
+                gtExplosives,
+                gtStructure: begin
+// Run the calcs only once we know we have a type that will need damage
+                        if hwRound(hwAbs(Gear^.X-fX)+hwAbs(Gear^.Y-fY)) < dmgBase then
+                            dmg:= dmgBase - max(hwRound(Distance(Gear^.X - fX, Gear^.Y - fY)),Gear^.Radius);
+                        if dmg > 1 then
+                            begin
+                            dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
+                            //AddFileLog('Damage: ' + inttostr(dmg));
+                            if (Mask and EXPLNoDamage) = 0 then
+                                begin
+                                if not Gear^.Invulnerable then
+                                    ApplyDamage(Gear, AttackingHog, dmg, dsExplosion)
+                                else
+                                    Gear^.State:= Gear^.State or gstWinner;
+                                end;
+                            if ((Mask and EXPLDoNotTouchAny) = 0) and (((Mask and EXPLDoNotTouchHH) = 0) or (Gear^.Kind <> gtHedgehog)) then
+                                begin
+                                DeleteCI(Gear);
+                                Gear^.dX:= Gear^.dX + SignAs(_0_005 * dmg + cHHKick, Gear^.X - fX)/(Gear^.Density/_3);
+                                Gear^.dY:= Gear^.dY + SignAs(_0_005 * dmg + cHHKick, Gear^.Y - fY)/(Gear^.Density/_3);
+
+                                Gear^.State:= (Gear^.State or gstMoving) and (not gstLoser);
+                                if not Gear^.Invulnerable then
+                                    Gear^.State:= (Gear^.State or gstMoving) and (not gstWinner);
+                                Gear^.Active:= true;
+                                if Gear^.Kind <> gtFlame then FollowGear:= Gear
+                                end;
+                            if ((Mask and EXPLPoisoned) <> 0) and (Gear^.Kind = gtHedgehog) and (not Gear^.Invulnerable) then
+                                Gear^.Hedgehog^.Effects[hePoisoned] := true;
+                            end;
+
+                        end;
+                gtGrave: begin
+// Run the calcs only once we know we have a type that will need damage
+                        if hwRound(hwAbs(Gear^.X-fX)+hwAbs(Gear^.Y-fY)) < dmgBase then
+                            dmg:= dmgBase - hwRound(Distance(Gear^.X - fX, Gear^.Y - fY));
+                        if dmg > 1 then
+                            begin
+                            dmg:= ModifyDamage(min(dmg div 2, Radius), Gear);
+                            Gear^.dY:= - _0_004 * dmg;
+                            Gear^.Active:= true
+                            end
+                        end;
+            end;
+        end;
+    Gear:= Gear^.NextGear
+    end;
+
+if (Mask and EXPLDontDraw) = 0 then
+    if (GameFlags and gfSolidLand) = 0 then
+        begin
+        cnt:= DrawExplosion(X, Y, Radius) div 1608; // approx 2 16x16 circles to erase per chunk
+        if (cnt > 0) and (SpritesData[sprChunk].Texture <> nil) then
+            for i:= 0 to cnt do
+                AddVisualGear(X, Y, vgtChunk)
+        end;
+
+uAIMisc.AwareOfExplosion(0, 0, 0)
+end;
+
+function ModifyDamage(dmg: Longword; Gear: PGear): Longword;
+var i: hwFloat;
+begin
+(* Invulnerability cannot be placed in here due to still needing kicks
+   Not without a new damage machine.
+   King check should be in here instead of ApplyDamage since Tiy wants them kicked less
+*)
+i:= _1;
+if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then
+    i:= _1_5;
+if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.King) then
+    ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent * _0_5)
+else
+    ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent)
+end;
+
+procedure ApplyDamage(Gear: PGear; AttackerHog: PHedgehog; Damage: Longword; Source: TDamageSource);
+var s: shortstring;
+    vampDmg, tmpDmg, i: Longword;
+    vg: PVisualGear;
+begin
+    if Damage = 0 then
+        exit; // nothing to apply
+
+    if (Gear^.Kind = gtHedgehog) then
+        begin
+        Gear^.LastDamage := AttackerHog;
+
+        Gear^.Hedgehog^.Team^.Clan^.Flawless:= false;
+        HHHurt(Gear^.Hedgehog, Source);
+        AddDamageTag(hwRound(Gear^.X), hwRound(Gear^.Y), Damage, Gear^.Hedgehog^.Team^.Clan^.Color);
+        tmpDmg:= min(Damage, max(0,Gear^.Health-Gear^.Damage));
+        if (Gear <> CurrentHedgehog^.Gear) and (CurrentHedgehog^.Gear <> nil) and (tmpDmg >= 1) then
+            begin
+            if cVampiric then
+                begin
+                vampDmg:= hwRound(int2hwFloat(tmpDmg)*_0_8);
+                if vampDmg >= 1 then
+                    begin
+                    // was considering pulsing on attack, Tiy thinks it should be permanent while in play
+                    //CurrentHedgehog^.Gear^.State:= CurrentHedgehog^.Gear^.State or gstVampiric;
+                    inc(CurrentHedgehog^.Gear^.Health,vampDmg);
+                    str(vampDmg, s);
+                    s:= '+' + s;
+                    AddCaption(s, CurrentHedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
+                    RenderHealth(CurrentHedgehog^);
+                    RecountTeamHealth(CurrentHedgehog^.Team);
+                    i:= 0;
+                    while i < vampDmg do
+                        begin
+                        vg:= AddVisualGear(hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y), vgtStraightShot);
+                        if vg <> nil then
+                            with vg^ do
+                                begin
+                                Tint:= $FF0000FF;
+                                State:= ord(sprHealth)
+                                end;
+                        inc(i, 5);
+                        end;
+                    end
+                end;
+        if ((GameFlags and gfKarma) <> 0) and 
+        ((GameFlags and gfInvulnerable) = 0)
+        and (not CurrentHedgehog^.Gear^.Invulnerable) then
+            begin // this cannot just use Damage or it interrupts shotgun and gets you called stupid
+            inc(CurrentHedgehog^.Gear^.Karma, tmpDmg);
+            CurrentHedgehog^.Gear^.LastDamage := CurrentHedgehog;
+            spawnHealthTagForHH(CurrentHedgehog^.Gear, tmpDmg);
+            end;
+        uStats.HedgehogDamaged(Gear, AttackerHog, Damage, false);    
+        end;
+    end
+    else if Gear^.Kind <> gtStructure then // not gtHedgehog nor gtStructure
+        begin
+        Gear^.Hedgehog:= AttackerHog;
+        end;
+    inc(Gear^.Damage, Damage);
+    
+    ScriptCall('onGearDamage', Gear^.UID, Damage);
+end;
+
+procedure spawnHealthTagForHH(HHGear: PGear; dmg: Longword);
+var tag: PVisualGear;
+begin
+tag:= AddVisualGear(hwRound(HHGear^.X), hwRound(HHGear^.Y), vgtHealthTag, dmg);
+if (tag <> nil) then
+    tag^.Hedgehog:= HHGear^.Hedgehog; // the tag needs the tag to determine the text color
+AllInactive:= false;
+HHGear^.Active:= true;
+end;
+    
+procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
+begin
+if (Source = dsFall) or (Source = dsExplosion) then
+    case random(3) of
+        0: PlaySound(sndOoff1, Hedgehog^.Team^.voicepack);
+        1: PlaySound(sndOoff2, Hedgehog^.Team^.voicepack);
+        2: PlaySound(sndOoff3, Hedgehog^.Team^.voicepack);
+    end
+else if (Source = dsPoison) then
+    case random(2) of
+        0: PlaySound(sndPoisonCough, Hedgehog^.Team^.voicepack);
+        1: PlaySound(sndPoisonMoan, Hedgehog^.Team^.voicepack);
+    end
+else
+    case random(4) of
+        0: PlaySound(sndOw1, Hedgehog^.Team^.voicepack);
+        1: PlaySound(sndOw2, Hedgehog^.Team^.voicepack);
+        2: PlaySound(sndOw3, Hedgehog^.Team^.voicepack);
+        3: PlaySound(sndOw4, Hedgehog^.Team^.voicepack);
+    end
+end;
+
+procedure CheckHHDamage(Gear: PGear);
+var 
+    dmg: Longword;
+    i: LongInt;
+    particle: PVisualGear;
+begin
+    if _0_4 < Gear^.dY then
+        begin
+        dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
+        PlaySound(sndBump);
+        if dmg < 1 then
+            exit;
+
+        for i:= min(12, (3 + dmg div 10)) downto 0 do
+            begin
+            particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
+            if particle <> nil then
+                particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
+            end;
+
+        if (Gear^.Invulnerable) then
+            exit;
+
+        //if _0_6 < Gear^.dY then
+        //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
+        //else
+        //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
+
+        if Gear^.LastDamage <> nil then
+            ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
+        else
+            ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
+    end
+end;
+
+
+procedure CalcRotationDirAngle(Gear: PGear);
+var 
+    dAngle: real;
+begin
+    dAngle := (Gear^.dX.QWordValue + Gear^.dY.QWordValue) / $80000000;
+    if not Gear^.dX.isNegative then
+        Gear^.DirAngle := Gear^.DirAngle + dAngle
+    else
+        Gear^.DirAngle := Gear^.DirAngle - dAngle;
+
+    if Gear^.DirAngle < 0 then
+        Gear^.DirAngle := Gear^.DirAngle + 360
+    else if 360 < Gear^.DirAngle then
+        Gear^.DirAngle := Gear^.DirAngle - 360
+end;
+
+function CheckGearDrowning(Gear: PGear): boolean;
+var 
+    skipSpeed, skipAngle, skipDecay: hwFloat;
+    i, maxDrops, X, Y: LongInt;
+    vdX, vdY: real;
+    particle: PVisualGear;
+    isSubmersible: boolean;
+begin
+    // probably needs tweaking. might need to be in a case statement based upon gear type
+    Y:= hwRound(Gear^.Y);
+    if cWaterLine < Y + Gear^.Radius then
+        begin
+        isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
+        skipSpeed := _0_25;
+        skipAngle := _1_9;
+        skipDecay := _0_87;
+        X:= hwRound(Gear^.X);
+        vdX:= hwFloat2Float(Gear^.dX);
+        vdY:= hwFloat2Float(Gear^.dY);
+        // this could perhaps be a tiny bit higher.
+        if  (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed)
+        and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
+            begin
+            Gear^.dY.isNegative := true;
+            Gear^.dY := Gear^.dY * skipDecay;
+            Gear^.dX := Gear^.dX * skipDecay;
+            CheckGearDrowning := false;
+            PlaySound(sndSkip)
+            end
+        else
+            begin
+            if not isSubmersible then
+                begin
+                CheckGearDrowning := true;
+                Gear^.State := gstDrowning;
+                Gear^.RenderTimer := false;
+                if (Gear^.Kind <> gtSniperRifleShot) and (Gear^.Kind <> gtShotgunShot)
+                and (Gear^.Kind <> gtDEagleShot) and (Gear^.Kind <> gtSineGunShot) then
+                    if Gear^.Kind = gtHedgehog then
+                        begin
+                        if Gear^.Hedgehog^.Effects[heResurrectable] then
+                            ResurrectHedgehog(Gear)
+                        else
+                            begin
+                            Gear^.doStep := @doStepDrowningGear;
+                            Gear^.State := Gear^.State and (not gstHHDriven);
+                            AddCaption(Format(GetEventString(eidDrowned), Gear^.Hedgehog^.Name), cWhiteColor, capgrpMessage);
+                            end
+                        end
+                    else
+                        Gear^.doStep := @doStepDrowningGear;
+                        if Gear^.Kind = gtFlake then
+                            exit // skip splashes 
+                end;
+            if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
+            or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
+            and (CurAmmoGear^.dY < _0_01))) then
+                // don't play splash if they are already way past the surface
+                PlaySound(sndSplash)
+            end;
+
+        if ((cReducedQuality and rqPlainSplash) = 0)
+        and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
+        or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
+        and (CurAmmoGear^.dY < _0_01)))) then
+            begin
+            AddVisualGear(X, cWaterLine, vgtSplash);
+
+            maxDrops := (Gear^.Radius div 2) + round(vdX * Gear^.Radius * 2) + round(vdY * Gear^.Radius * 2);
+            for i:= max(maxDrops div 3, min(32, Random(maxDrops))) downto 0 do
+                begin
+                particle := AddVisualGear(X - 3 + Random(6), cWaterLine, vgtDroplet);
+                if particle <> nil then
+                    begin
+                    particle^.dX := particle^.dX - vdX / 10;
+                    particle^.dY := particle^.dY - vdY / 5;
+                    end
+                end
+            end;
+        if isSubmersible and (CurAmmoGear^.Pos = 0) then
+            CurAmmoGear^.Pos := 1000
+        end
+    else
+        CheckGearDrowning := false;
+end;
+
+
+procedure ResurrectHedgehog(gear: PGear);
+var tempTeam : PTeam;
+begin
+    AttackBar:= 0;
+    gear^.dX := _0;
+    gear^.dY := _0;
+    gear^.Damage := 0;
+    gear^.Health := gear^.Hedgehog^.InitialHealth;
+    gear^.Hedgehog^.Effects[hePoisoned] := false;
+    if not CurrentHedgehog^.Effects[heResurrectable] then
+        with CurrentHedgehog^ do 
+            begin
+            inc(Team^.stats.AIKills);
+            FreeTexture(Team^.AIKillsTex);
+            Team^.AIKillsTex := RenderStringTex(inttostr(Team^.stats.AIKills), Team^.Clan^.Color, fnt16);
+            end;
+    tempTeam := gear^.Hedgehog^.Team;
+    DeleteCI(gear);
+    FindPlace(gear, false, 0, LAND_WIDTH, true); 
+    if gear <> nil then
+        begin
+        RenderHealth(gear^.Hedgehog^);
+        ScriptCall('onGearResurrect', gear^.uid);
+        gear^.State := gstWait;
+    end;
+    RecountTeamHealth(tempTeam);
+end;
+
+function CountNonZeroz(x, y, r, c: LongInt): LongInt;
+var i: LongInt;
+    count: LongInt = 0;
+begin
+if (y and LAND_HEIGHT_MASK) = 0 then
+    for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do
+        if Land[y, i] <> 0 then
+            begin
+            inc(count);
+            if count = c then
+                exit(count)
+            end;
+CountNonZeroz:= count;
+end;
+
+procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
+var x: LongInt;
+    y, sy: LongInt;
+    ar: array[0..511] of TPoint;
+    ar2: array[0..1023] of TPoint;
+    cnt, cnt2: Longword;
+    delta: LongInt;
+    reallySkip, tryAgain: boolean;
+begin
+reallySkip:= false; // try not skipping proximity at first
+tryAgain:= true;
+while tryAgain do
+    begin
+    delta:= 250;
+    cnt2:= 0;
+    repeat
+        x:= Left + LongInt(GetRandom(Delta));
+        repeat
+            inc(x, Delta);
+            cnt:= 0;
+            y:= min(1024, topY) - 2 * Gear^.Radius;
+            while y < cWaterLine do
+                begin
+                repeat
+                    inc(y, 2);
+                until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) = 0);
+
+                sy:= y;
+
+                repeat
+                    inc(y);
+                until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0);
+
+                if (y - sy > Gear^.Radius * 2)
+                    and (((Gear^.Kind = gtExplosives)
+                    and (y < cWaterLine)
+                    and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 60, 60) = nil))
+                    and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius))
+                or
+                    ((Gear^.Kind <> gtExplosives)
+                    and (y < cWaterLine)
+                    and (reallySkip or (CheckGearsNear(x, y - Gear^.Radius, [gtFlame, gtHedgehog, gtMine, gtCase, gtExplosives], 110, 110) = nil)))) then
+                 
+                          begin
+                    ar[cnt].X:= x;
+                    if withFall then
+                        ar[cnt].Y:= sy + Gear^.Radius
+                    else
+                        ar[cnt].Y:= y - Gear^.Radius;
+                    inc(cnt)
+                    end;
+
+                inc(y, 45)
+                end;
+
+            if cnt > 0 then
+                with ar[GetRandom(cnt)] do
+                    begin
+                    ar2[cnt2].x:= x;
+                    ar2[cnt2].y:= y;
+                    inc(cnt2)
+                    end
+        until (x + Delta > Right);
+
+        dec(Delta, 60)
+    until (cnt2 > 0) or (Delta < 70);
+    if (cnt2 = 0) and skipProximity and (not reallySkip) then
+        tryAgain:= true
+    else tryAgain:= false;
+    reallySkip:= true;
+    end;
+
+if cnt2 > 0 then
+    with ar2[GetRandom(cnt2)] do
+        begin
+        Gear^.X:= int2hwFloat(x);
+        Gear^.Y:= int2hwFloat(y);
+        AddFileLog('Assigned Gear coordinates (' + inttostr(x) + ',' + inttostr(y) + ')');
+        end
+    else
+    begin
+    OutError('Can''t find place for Gear', false);
+    if Gear^.Kind = gtHedgehog then
+        Gear^.Hedgehog^.Effects[heResurrectable] := false;
+    DeleteGear(Gear);
+    Gear:= nil
+    end
+end;
+
+function CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
+var t: PGear;
+begin
+t:= GearsList;
+rX:= sqr(rX);
+rY:= sqr(rY);
+
+while t <> nil do
+    begin
+    if (t <> Gear) and (t^.Kind = Kind) then
+        if not((hwSqr(Gear^.X - t^.X) / rX + hwSqr(Gear^.Y - t^.Y) / rY) > _1) then
+        exit(t);
+    t:= t^.NextGear
+    end;
+
+CheckGearNear:= nil
+end;
+
+
+function CheckGearsNear(mX, mY: LongInt; Kind: TGearsType; rX, rY: LongInt): PGear;
+var t: PGear;
+begin
+t:= GearsList;
+rX:= sqr(rX);
+rY:= sqr(rY);
+while t <> nil do
+    begin
+    if t^.Kind in Kind then
+        if not (hwSqr(int2hwFloat(mX) - t^.X) / rX + hwSqr(int2hwFloat(mY) - t^.Y) / rY > _1) then
+            exit(t);
+    t:= t^.NextGear
+    end;
+CheckGearsNear:= nil
+end;
+end.