hedgewars/GSHandlers.inc
changeset 6580 6155187bf599
parent 6556 faa47a7e614a
child 6700 e04da46ee43c
equal deleted inserted replaced
6579:fc52f7c22c9b 6580:6155187bf599
    51     if steps > 1 then
    51     if steps > 1 then
    52         begin
    52         begin
    53         sX:= dX / steps;
    53         sX:= dX / steps;
    54         sY:= dY / steps;
    54         sY:= dY / steps;
    55         end
    55         end
       
    56         
    56     else
    57     else
    57         begin
    58         begin
    58         sX:= dX;
    59         sX:= dX;
    59         sY:= dY;
    60         sY:= dY;
    60         end;
    61         end;
    86             d := r - hwRound(Distance(gi^.X - x, gi^.Y - y));
    87             d := r - hwRound(Distance(gi^.X - x, gi^.Y - y));
    87             if (d > 1) and (not gi^.Invulnerable) and (GetRandom(2) = 0) then
    88             if (d > 1) and (not gi^.Invulnerable) and (GetRandom(2) = 0) then
    88                 begin
    89                 begin
    89                 if (CurrentHedgehog^.Gear = gi) then
    90                 if (CurrentHedgehog^.Gear = gi) then
    90                     PlaySound(sndOops, gi^.Hedgehog^.Team^.voicepack)
    91                     PlaySound(sndOops, gi^.Hedgehog^.Team^.voicepack)
       
    92                     
    91                 else
    93                 else
    92                     begin
    94                     begin
    93                     if (gi^.State and gstMoving) = 0 then
    95                     if (gi^.State and gstMoving) = 0 then
    94                         gi^.State := gi^.State or gstLoser;
    96                         gi^.State := gi^.State or gstLoser;
       
    97                         
    95                     if d > r div 2 then
    98                     if d > r div 2 then
    96                         PlaySound(sndNooo, gi^.Hedgehog^.Team^.voicepack)
    99                         PlaySound(sndNooo, gi^.Hedgehog^.Team^.voicepack) 
    97                     else
   100                     else
    98                         PlaySound(sndUhOh, gi^.Hedgehog^.Team^.voicepack);
   101                         PlaySound(sndUhOh, gi^.Hedgehog^.Team^.voicepack);
    99                     end;
   102                     end;
   100                 end;
   103                 end;
   101             end;
   104             end;
       
   105             
   102         gi := gi^.NextGear
   106         gi := gi^.NextGear
   103         end;
   107         end;
   104 end;
   108 end;
   105 
   109 
   106 procedure HideHog(HH: PHedgehog);
   110 procedure HideHog(HH: PHedgehog);
   107 begin
   111 begin
   108 ScriptCall('onHogHide', HH^.Gear^.Uid);
   112     ScriptCall('onHogHide', HH^.Gear^.Uid);
   109 DeleteCI(HH^.Gear);
   113     DeleteCI(HH^.Gear);
   110 if FollowGear = HH^.Gear then FollowGear:= nil;
   114     if FollowGear = HH^.Gear then
   111 if lastGearByUID = HH^.Gear then lastGearByUID := nil;
   115         FollowGear:= nil;
   112 RemoveGearFromList(HH^.Gear);
   116         
   113 with HH^.Gear^ do
   117     if lastGearByUID = HH^.Gear then
       
   118         lastGearByUID := nil;
       
   119         
       
   120     RemoveGearFromList(HH^.Gear);
       
   121     with HH^.Gear^ do
       
   122         begin
       
   123         Z := cHHZ;
       
   124         Active := false;
       
   125         State:= State and (not (gstHHDriven or gstAttacking or gstAttacked));
       
   126         Message := Message and (not gmAttack);
       
   127     end;
       
   128     HH^.GearHidden:= HH^.Gear;
       
   129     HH^.Gear:= nil
       
   130 end;
       
   131 
       
   132 procedure RestoreHog(HH: PHedgehog);
       
   133 begin
       
   134     HH^.Gear:=HH^.GearHidden;
       
   135     HH^.GearHidden:= nil;
       
   136     InsertGearToList(HH^.Gear);
       
   137     HH^.Gear^.State:= (HH^.Gear^.State and (not (gstHHDriven or gstInvisible or gstAttacking))) or gstAttacked;
       
   138     AddGearCI(HH^.Gear);
       
   139     HH^.Gear^.Active:= true;
       
   140     ScriptCall('onHogRestore', HH^.Gear^.Uid)
       
   141 end;
       
   142 
       
   143 ////////////////////////////////////////////////////////////////////////////////
       
   144 procedure CheckCollision(Gear: PGear); inline;
       
   145 begin
       
   146     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
       
   147     or (TestCollisionYwithGear(Gear, hwSign(Gear^.dY)) <> 0) then
       
   148         Gear^.State := Gear^.State or gstCollision
       
   149     else
       
   150         Gear^.State := Gear^.State and (not gstCollision)
       
   151 end;
       
   152 
       
   153 procedure CheckCollisionWithLand(Gear: PGear); inline;
       
   154 begin
       
   155     if TestCollisionX(Gear, hwSign(Gear^.dX))
       
   156     or TestCollisionY(Gear, hwSign(Gear^.dY)) then
       
   157         Gear^.State := Gear^.State or gstCollision
       
   158     else 
       
   159         Gear^.State := Gear^.State and (not gstCollision)
       
   160 end;
       
   161 
       
   162 
       
   163 ////////////////////////////////////////////////////////////////////////////////
       
   164 
       
   165 
       
   166 ////////////////////////////////////////////////////////////////////////////////
       
   167 procedure doStepDrowningGear(Gear: PGear);
   114     begin
   168     begin
   115     Z := cHHZ;
       
   116     Active := false;
       
   117     State:= State and (not (gstHHDriven or gstAttacking or gstAttacked));
       
   118     Message := Message and (not gmAttack);
       
   119     end;
       
   120 HH^.GearHidden:= HH^.Gear;
       
   121 HH^.Gear:= nil
       
   122 end;
       
   123 
       
   124 procedure RestoreHog(HH: PHedgehog);
       
   125 begin
       
   126 HH^.Gear:=HH^.GearHidden;
       
   127 HH^.GearHidden:= nil;
       
   128 InsertGearToList(HH^.Gear);
       
   129 HH^.Gear^.State:= (HH^.Gear^.State and (not (gstHHDriven or gstInvisible or gstAttacking))) or gstAttacked;
       
   130 AddGearCI(HH^.Gear);
       
   131 HH^.Gear^.Active:= true;
       
   132 ScriptCall('onHogRestore', HH^.Gear^.Uid)
       
   133 end;
       
   134 
       
   135 ////////////////////////////////////////////////////////////////////////////////
       
   136 procedure CheckCollision(Gear: PGear); inline;
       
   137 begin
       
   138     if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) or (TestCollisionYwithGear(Gear, hwSign(Gear^.dY)) <> 0) then
       
   139         Gear^.State := Gear^.State or gstCollision
       
   140     else Gear^.State := Gear^.State and (not gstCollision)
       
   141 end;
       
   142 
       
   143 procedure CheckCollisionWithLand(Gear: PGear); inline;
       
   144 begin
       
   145     if TestCollisionX(Gear, hwSign(Gear^.dX)) or TestCollisionY(Gear, hwSign(Gear^.dY)
       
   146        )
       
   147         then Gear^.State := Gear^.State or      gstCollision
       
   148     else Gear^.State := Gear^.State and (not gstCollision)
       
   149 end;
       
   150 
       
   151 
       
   152 ////////////////////////////////////////////////////////////////////////////////
       
   153 
       
   154 
       
   155 ////////////////////////////////////////////////////////////////////////////////
       
   156 procedure doStepDrowningGear(Gear: PGear);
       
   157 begin
       
   158     AllInactive := false;
   169     AllInactive := false;
   159     Gear^.Y := Gear^.Y + cDrownSpeed;
   170     Gear^.Y := Gear^.Y + cDrownSpeed;
   160     Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
   171     Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
   161     // Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
   172     // Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
   162     if ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
   173     if ((not SuddenDeathDmg and (cWaterOpacity < $FF))
       
   174     or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
   163         if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
   175         if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
   164             AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble)
   176             AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble)
   165     else if Random(12) = 0 then
   177     else if Random(12) = 0 then
   166              AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble);
   178              AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble);
   167     if (not SuddenDeathDmg and (cWaterOpacity > $FE)) or (SuddenDeathDmg and (cSDWaterOpacity > $FE)) or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
   179     if (not SuddenDeathDmg and (cWaterOpacity > $FE))
       
   180     or (SuddenDeathDmg and (cSDWaterOpacity > $FE))
       
   181     or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
   168         DeleteGear(Gear);
   182         DeleteGear(Gear);
   169 end;
   183     end;
   170 
   184 
   171 ////////////////////////////////////////////////////////////////////////////////
   185 ////////////////////////////////////////////////////////////////////////////////
   172 procedure doStepFallingGear(Gear: PGear);
   186 procedure doStepFallingGear(Gear: PGear);
   173 var 
   187 var 
   174     isFalling: boolean;
   188     isFalling: boolean;
   176     tdX, tdY: hwFloat;
   190     tdX, tdY: hwFloat;
   177     collV, collH: LongInt;
   191     collV, collH: LongInt;
   178     land: word;
   192     land: word;
   179 begin
   193 begin
   180     // clip velocity at 1.9 - over 1 per pixel, but really shouldn't cause many actual problems.
   194     // clip velocity at 1.9 - over 1 per pixel, but really shouldn't cause many actual problems.
   181     if Gear^.dX.QWordValue > 8160437862 then Gear^.dX.QWordValue:= 8160437862;
   195     if Gear^.dX.QWordValue > 8160437862 then
   182     if Gear^.dY.QWordValue > 8160437862 then Gear^.dY.QWordValue:= 8160437862;
   196         Gear^.dX.QWordValue:= 8160437862;
       
   197     if Gear^.dY.QWordValue > 8160437862 then
       
   198         Gear^.dY.QWordValue:= 8160437862;
   183     Gear^.State := Gear^.State and (not gstCollision);
   199     Gear^.State := Gear^.State and (not gstCollision);
   184     collV := 0;
   200     collV := 0;
   185     collH := 0;
   201     collH := 0;
   186     tdX := Gear^.dX;
   202     tdX := Gear^.dX;
   187     tdY := Gear^.dY;
   203     tdY := Gear^.dY;
   188 
   204 
   189 
   205 
   190 // might need some testing/adjustments - just to avoid projectiles to fly forever (accelerated by wind/skips)
   206 // might need some testing/adjustments - just to avoid projectiles to fly forever (accelerated by wind/skips)
   191     if (hwRound(Gear^.X) < LAND_WIDTH div -2) or (hwRound(Gear^.X) > LAND_WIDTH * 3 div 2) then Gear^.State := Gear^.State or gstCollision;
   207     if (hwRound(Gear^.X) < LAND_WIDTH div -2)
       
   208     or (hwRound(Gear^.X) > LAND_WIDTH * 3 div 2) then
       
   209         Gear^.State := Gear^.State or gstCollision;
   192 
   210 
   193     if Gear^.dY.isNegative then
   211     if Gear^.dY.isNegative then
   194         begin
   212         begin
   195         isFalling := true;
   213         isFalling := true;
   196         land:= TestCollisionYwithGear(Gear, -1);
   214         land:= TestCollisionYwithGear(Gear, -1);
   197         if land <> 0 then
   215         if land <> 0 then
   198             begin
   216             begin
   199             collV := -1;
   217             collV := -1;
   200             if land and lfIce <> 0 then Gear^.dX := Gear^.dX * (_0_9 + Gear^.Friction * _0_1)
   218             if land and lfIce <> 0 then
   201             else Gear^.dX := Gear^.dX * Gear^.Friction;
   219                 Gear^.dX := Gear^.dX * (_0_9 + Gear^.Friction * _0_1)
       
   220             else
       
   221                 Gear^.dX := Gear^.dX * Gear^.Friction;
   202 
   222 
   203             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
   223             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
   204             Gear^.State := Gear^.State or gstCollision
   224             Gear^.State := Gear^.State or gstCollision
   205             end
   225             end
   206         else if (Gear^.AdvBounce=1) and (TestCollisionYwithGear(Gear, 1) <> 0) then collV := 1;
   226         else if (Gear^.AdvBounce=1) and (TestCollisionYwithGear(Gear, 1) <> 0) then
       
   227             collV := 1;
   207         end
   228         end
   208     else 
   229     else 
   209         begin // Gear^.dY.isNegative is false
   230         begin // Gear^.dY.isNegative is false
   210         land:= TestCollisionYwithGear(Gear, 1);
   231         land:= TestCollisionYwithGear(Gear, 1);
   211         if land <> 0 then
   232         if land <> 0 then
   237         Gear^.State := Gear^.State or gstCollision
   258         Gear^.State := Gear^.State or gstCollision
   238         end
   259         end
   239     else if (Gear^.AdvBounce=1) and TestCollisionXwithGear(Gear, -hwSign(Gear^.dX)) then
   260     else if (Gear^.AdvBounce=1) and TestCollisionXwithGear(Gear, -hwSign(Gear^.dX)) then
   240         collH := -hwSign(Gear^.dX); 
   261         collH := -hwSign(Gear^.dX); 
   241     //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
   262     //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
   242     if (Gear^.AdvBounce=1) and (collV <>0) and (collH <> 0) and ((collV=-1) or ((tdX.QWordValue +
   263     if (Gear^.AdvBounce=1) and (collV <>0) and (collH <> 0) and ((collV=-1)
   243        tdY.QWordValue) > _0_2.QWordValue)) then
   264     or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)) then
   244         begin
   265         begin
   245         Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
   266         Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
   246         Gear^.dY := tdX*Gear^.Elasticity;
   267         Gear^.dY := tdX*Gear^.Elasticity;
   247         //*Gear^.Friction;
   268         //*Gear^.Friction;
   248         Gear^.dY.isNegative := not tdY.isNegative;
   269         Gear^.dY.isNegative := not tdY.isNegative;
   249         isFalling := false;
   270         isFalling := false;
   250         Gear^.AdvBounce := 10;
   271         Gear^.AdvBounce := 10;
   251         end;
   272         end;
   252 
   273 
   253     if Gear^.AdvBounce > 1 then dec(Gear^.AdvBounce);
   274     if Gear^.AdvBounce > 1 then
       
   275         dec(Gear^.AdvBounce);
   254 
   276 
   255     if isFalling then
   277     if isFalling then
   256         begin
   278         begin
   257         Gear^.dY := Gear^.dY + cGravity;
   279         Gear^.dY := Gear^.dY + cGravity;
   258         if (GameFlags and gfMoreWind) <> 0 then Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
   280         if (GameFlags and gfMoreWind) <> 0 then
   259         end;
   281             Gear^.dX := Gear^.dX + cWindSpeed / Gear^.Density
       
   282             end;
   260 
   283 
   261     Gear^.X := Gear^.X + Gear^.dX;
   284     Gear^.X := Gear^.X + Gear^.dX;
   262     Gear^.Y := Gear^.Y + Gear^.dY;
   285     Gear^.Y := Gear^.Y + Gear^.dY;
   263     if Gear^.Kind <> gtBee then
   286     if Gear^.Kind <> gtBee then
   264         CheckGearDrowning(Gear);
   287         CheckGearDrowning(Gear);
   265     //if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _0_0002) and
   288     //if (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) < _0_0002) and
   266     if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then
   289     if (not isFalling) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_02.QWordValue) then
   267         Gear^.State := Gear^.State and (not gstMoving)
   290         Gear^.State := Gear^.State and (not gstMoving)
   268     else
   291     else
   269         Gear^.State := Gear^.State or      gstMoving;
   292         Gear^.State := Gear^.State or gstMoving;
   270 
   293 
   271     if (Gear^.nImpactSounds > 0) and 
   294     if (Gear^.nImpactSounds > 0) and (((Gear^.Kind <> gtMine) and (Gear^.Damage <> 0))
   272        (((Gear^.Kind <> gtMine) and (Gear^.Damage <> 0)) or 
   295     or ((Gear^.State and (gstCollision or gstMoving)) = (gstCollision or gstMoving))) and(((Gear^.Radius < 3) and (Gear^.dY < -_0_1))
   273           ((Gear^.State and (gstCollision or gstMoving)) = (gstCollision or gstMoving))) and
   296     or ((Gear^.Radius >= 3) and ((Gear^.dX.QWordValue > _0_1.QWordValue)
   274        (((Gear^.Radius < 3) and (Gear^.dY < -_0_1)) or
   297     or (Gear^.dY.QWordValue > _0_1.QWordValue)))) then
   275         ((Gear^.Radius >= 3) and ((Gear^.dX.QWordValue > _0_1.QWordValue) or 
       
   276           (Gear^.dY.QWordValue > _0_1.QWordValue)))) then
       
   277         PlaySound(TSound(ord(Gear^.ImpactSound) + LongInt(GetRandom(Gear^.nImpactSounds))), true);
   298         PlaySound(TSound(ord(Gear^.ImpactSound) + LongInt(GetRandom(Gear^.nImpactSounds))), true);
   278 end;
   299 end;
   279 
   300 
   280 ////////////////////////////////////////////////////////////////////////////////
   301 ////////////////////////////////////////////////////////////////////////////////
   281 procedure doStepBomb(Gear: PGear);
   302 procedure doStepBomb(Gear: PGear);
   297             gtHellishBomb: makeHogsWorry(Gear^.X, Gear^.Y, 90);
   318             gtHellishBomb: makeHogsWorry(Gear^.X, Gear^.Y, 90);
   298             gtGasBomb: makeHogsWorry(Gear^.X, Gear^.Y, 50);
   319             gtGasBomb: makeHogsWorry(Gear^.X, Gear^.Y, 50);
   299         end;
   320         end;
   300 
   321 
   301     if (Gear^.Kind = gtBall) and ((Gear^.State and gstTmpFlag) <> 0) then
   322     if (Gear^.Kind = gtBall) and ((Gear^.State and gstTmpFlag) <> 0) then
   302     begin
   323         begin
   303         CheckCollision(Gear);
   324         CheckCollision(Gear);
   304         if (Gear^.State and gstCollision) <> 0 then
   325         if (Gear^.State and gstCollision) <> 0 then
   305             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, Gear^.Hedgehog, EXPLDontDraw or EXPLNoGfx);
   326             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, Gear^.Hedgehog, EXPLDontDraw or EXPLNoGfx);
   306     end;
   327     end;
   307 
   328 
   308     if (Gear^.Kind = gtGasBomb) and ((GameTicks mod 200) = 0) then
   329     if (Gear^.Kind = gtGasBomb) and ((GameTicks mod 200) = 0) then
   309     begin
   330         begin
   310         vg:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeWhite);
   331         vg:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeWhite);
   311         if vg <> nil then
   332         if vg <> nil then
   312             vg^.Tint:= $FFC0C000;
   333             vg^.Tint:= $FFC0C000;
   313     end;
   334     end;
   314 
   335 
   315     if Gear^.Timer = 0 then
   336     if Gear^.Timer = 0 then
   316     begin
   337         begin
   317         case Gear^.Kind of 
   338         case Gear^.Kind of 
   318             gtGrenade: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   339             gtGrenade: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   319             gtBall: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 40, Gear^.Hedgehog, EXPLAutoSound);
   340             gtBall: doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 40, Gear^.Hedgehog, EXPLAutoSound);
   320             gtClusterBomb: 
   341             gtClusterBomb: 
   321                 begin
   342                 begin
   322                     x := hwRound(Gear^.X);
   343                 x := hwRound(Gear^.X);
   323                     y := hwRound(Gear^.Y);
   344                 y := hwRound(Gear^.Y);
   324                     doMakeExplosion(x, y, 20, Gear^.Hedgehog, EXPLAutoSound);
   345                 doMakeExplosion(x, y, 20, Gear^.Hedgehog, EXPLAutoSound);
   325                     for i:= 0 to 4 do
   346                 for i:= 0 to 4 do
   326                         begin
   347                     begin
   327                         dX := rndSign(GetRandom * _0_1) + Gear^.dX / 5;
   348                     dX := rndSign(GetRandom * _0_1) + Gear^.dX / 5;
   328                         dY := (GetRandom - _3) * _0_08;
   349                     dY := (GetRandom - _3) * _0_08;
   329                         FollowGear := AddGear(x, y, gtCluster, 0, dX, dY, 25)
   350                     FollowGear := AddGear(x, y, gtCluster, 0, dX, dY, 25)
   330                         end
   351                     end
   331                 end;
   352                 end;
   332             gtWatermelon: 
   353             gtWatermelon: 
   333                 begin
   354                 begin
   334                 x := hwRound(Gear^.X);
   355                 x := hwRound(Gear^.X);
   335                 y := hwRound(Gear^.Y);
   356                 y := hwRound(Gear^.Y);
   380     end;
   401     end;
   381 
   402 
   382     CalcRotationDirAngle(Gear);
   403     CalcRotationDirAngle(Gear);
   383 
   404 
   384     if Gear^.Kind = gtHellishBomb then
   405     if Gear^.Kind = gtHellishBomb then
   385     begin
   406         begin
   386 
   407 
   387         if Gear^.Timer = 3000 then
   408         if Gear^.Timer = 3000 then
   388         begin
   409             begin
   389             Gear^.nImpactSounds := 0;
   410             Gear^.nImpactSounds := 0;
   390             PlaySound(sndHellish);
   411             PlaySound(sndHellish);
   391         end;
   412             end;
   392 
   413 
   393         if (GameTicks and $3F) = 0 then
   414         if (GameTicks and $3F) = 0 then
   394             if (Gear^.State and gstCollision) = 0 then
   415             if (Gear^.State and gstCollision) = 0 then
   395                 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace);
   416                 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace);
   396     end;
   417         end;
   397 end;
   418 end;
   398 
   419 
   399 ////////////////////////////////////////////////////////////////////////////////
   420 ////////////////////////////////////////////////////////////////////////////////
   400 procedure doStepMolotov(Gear: PGear);
   421 procedure doStepMolotov(Gear: PGear);
   401 var 
   422 var 
   412     // let's add some smoke depending on speed
   433     // let's add some smoke depending on speed
   413     s:= max(32,152 - hwRound(Distance(Gear^.dX,Gear^.dY)*120))+random(10);
   434     s:= max(32,152 - hwRound(Distance(Gear^.dX,Gear^.dY)*120))+random(10);
   414     if (GameTicks mod s) = 0 then
   435     if (GameTicks mod s) = 0 then
   415         begin
   436         begin
   416         // adjust angle to match the texture
   437         // adjust angle to match the texture
   417         if Gear^.dX.isNegative then i:= 130 else i:= 50;
   438         if Gear^.dX.isNegative then
       
   439             i:= 130
       
   440         else
       
   441             i:= 50;
       
   442             
   418         smoke:= AddVisualGear(hwRound(Gear^.X)-round(cos((Gear^.DirAngle+i) * pi / 180)*20), hwRound(Gear^.Y)-round(sin((Gear^.DirAngle+i) * pi / 180)*20), vgtSmoke);
   443         smoke:= AddVisualGear(hwRound(Gear^.X)-round(cos((Gear^.DirAngle+i) * pi / 180)*20), hwRound(Gear^.Y)-round(sin((Gear^.DirAngle+i) * pi / 180)*20), vgtSmoke);
   419         if smoke <> nil then smoke^.Scale:= 0.75;
   444         if smoke <> nil then
       
   445             smoke^.Scale:= 0.75;
   420         end;
   446         end;
   421 
   447 
   422     if (Gear^.State and gstCollision) <> 0 then
   448     if (Gear^.State and gstCollision) <> 0 then
   423     begin
   449         begin
   424         PlaySound(sndMolotov);
   450         PlaySound(sndMolotov);
   425         gX := hwRound(Gear^.X);
   451         gX := hwRound(Gear^.X);
   426         gY := hwRound(Gear^.Y);
   452         gY := hwRound(Gear^.Y);
   427         for i:= 0 to 4 do
   453         for i:= 0 to 4 do
   428             begin
   454             begin
   441                     Frame:= 2;
   467                     Frame:= 2;
   442                     Tint:= $41B83ED0 - i * $10081000;
   468                     Tint:= $41B83ED0 - i * $10081000;
   443                     Angle:= random * 360;
   469                     Angle:= random * 360;
   444                     dx:= 0.0000001;
   470                     dx:= 0.0000001;
   445                     dy:= 0;
   471                     dy:= 0;
   446                     if random(2) = 0 then dx := -dx;
   472                     if random(2) = 0 then
       
   473                         dx := -dx;
   447                     FrameTicks:= 750;
   474                     FrameTicks:= 750;
   448                     State:= ord(sprEgg)
   475                     State:= ord(sprEgg)
   449                     end;
   476                     end;
   450             end;
   477             end;
   451         for i:= 0 to 24 do
   478         for i:= 0 to 24 do
   457             AddGear(gX, gY, gtFlame, gstTmpFlag,-dX, dY, 0);
   484             AddGear(gX, gY, gtFlame, gstTmpFlag,-dX, dY, 0);
   458             AddGear(gX, gY, gtFlame, gstTmpFlag,-dX,-dY, 0);
   485             AddGear(gX, gY, gtFlame, gstTmpFlag,-dX,-dY, 0);
   459             end;
   486             end;
   460         DeleteGear(Gear);
   487         DeleteGear(Gear);
   461         exit
   488         exit
   462     end;
   489         end;
   463 end;
   490 end;
   464 
   491 
   465 ////////////////////////////////////////////////////////////////////////////////
   492 ////////////////////////////////////////////////////////////////////////////////
   466 
   493 
   467 procedure doStepCluster(Gear: PGear);
   494 procedure doStepCluster(Gear: PGear);
   468 begin
   495 begin
   469     AllInactive := false;
   496     AllInactive := false;
   470     doStepFallingGear(Gear);
   497     doStepFallingGear(Gear);
   471     if (Gear^.State and gstCollision) <> 0 then
   498     if (Gear^.State and gstCollision) <> 0 then
   472     begin
   499         begin
   473         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Timer, Gear^.Hedgehog, EXPLAutoSound);
   500         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Timer, Gear^.Hedgehog, EXPLAutoSound);
   474         DeleteGear(Gear);
   501         DeleteGear(Gear);
   475         exit
   502         exit
   476     end;
   503     end;
   477 
   504 
   478     if (Gear^.Kind = gtMelonPiece) or (Gear^.Kind = gtBall) then
   505     if (Gear^.Kind = gtMelonPiece)
       
   506     or (Gear^.Kind = gtBall) then
   479         CalcRotationDirAngle(Gear)
   507         CalcRotationDirAngle(Gear)
   480     else if (GameTicks and $1F) = 0 then
   508     else if (GameTicks and $1F) = 0 then
   481         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
   509         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
   482 end;
   510 end;
   483 
   511 
   484 ////////////////////////////////////////////////////////////////////////////////
   512 ////////////////////////////////////////////////////////////////////////////////
   485 procedure doStepShell(Gear: PGear);
   513 procedure doStepShell(Gear: PGear);
   486 begin
   514 begin
   487     AllInactive := false;
   515     AllInactive := false;
   488     if (GameFlags and gfMoreWind) = 0 then Gear^.dX := Gear^.dX + cWindSpeed;
   516     if (GameFlags and gfMoreWind) = 0 then
       
   517         Gear^.dX := Gear^.dX + cWindSpeed;
   489     doStepFallingGear(Gear);
   518     doStepFallingGear(Gear);
   490     if (Gear^.State and gstCollision) <> 0 then
   519     if (Gear^.State and gstCollision) <> 0 then
   491         begin
   520         begin
   492         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   521         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   493         DeleteGear(Gear);
   522         DeleteGear(Gear);
   501 procedure doStepSnowball(Gear: PGear);
   530 procedure doStepSnowball(Gear: PGear);
   502 var kick, i: LongInt;
   531 var kick, i: LongInt;
   503     particle: PVisualGear;
   532     particle: PVisualGear;
   504 begin
   533 begin
   505     AllInactive := false;
   534     AllInactive := false;
   506     if (GameFlags and gfMoreWind) = 0 then Gear^.dX := Gear^.dX + cWindSpeed;
   535     if (GameFlags and gfMoreWind) = 0 then
       
   536         Gear^.dX := Gear^.dX + cWindSpeed;
   507     doStepFallingGear(Gear);
   537     doStepFallingGear(Gear);
   508     CalcRotationDirAngle(Gear);
   538     CalcRotationDirAngle(Gear);
   509     if (Gear^.State and gstCollision) <> 0 then
   539     if (Gear^.State and gstCollision) <> 0 then
   510         begin
   540         begin
   511         kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
   541         kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
   513         Gear^.dX.isNegative:= not Gear^.dX.isNegative;
   543         Gear^.dX.isNegative:= not Gear^.dX.isNegative;
   514         AmmoShove(Gear, 1, kick);
   544         AmmoShove(Gear, 1, kick);
   515         for i:= 15 + kick div 10 downto 0 do
   545         for i:= 15 + kick div 10 downto 0 do
   516             begin
   546             begin
   517             particle := AddVisualGear(hwRound(Gear^.X) + Random(25), hwRound(Gear^.Y) + Random(25), vgtDust);
   547             particle := AddVisualGear(hwRound(Gear^.X) + Random(25), hwRound(Gear^.Y) + Random(25), vgtDust);
   518             if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
   548             if particle <> nil then
       
   549                 particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
   519             end;
   550             end;
   520         DeleteGear(Gear);
   551         DeleteGear(Gear);
   521         exit
   552         exit
   522         end;
   553         end;
   523     if ((GameTicks and $1F) = 0) and (Random(3) = 0) then
   554     if ((GameTicks and $1F) = 0) and (Random(3) = 0) then
   524         begin
   555         begin
   525         particle:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust);
   556         particle:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust);
   526         if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
   557         if particle <> nil then
       
   558             particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
   527         end
   559         end
   528 end;
   560 end;
   529 
   561 
   530 ////////////////////////////////////////////////////////////////////////////////
   562 ////////////////////////////////////////////////////////////////////////////////
   531 procedure doStepSnowflake(Gear: PGear);
   563 procedure doStepSnowflake(Gear: PGear);
   542 if gun then
   574 if gun then
   543     begin
   575     begin
   544     Gear^.State:= Gear^.State and (not gstInvisible);
   576     Gear^.State:= Gear^.State and (not gstInvisible);
   545     doStepFallingGear(Gear);
   577     doStepFallingGear(Gear);
   546     CheckCollision(Gear);
   578     CheckCollision(Gear);
   547     if ((Gear^.State and gstCollision) <> 0) or ((Gear^.State and gstMoving) = 0) then draw:= true;
   579     if ((Gear^.State and gstCollision) <> 0) or ((Gear^.State and gstMoving) = 0) then
       
   580         draw:= true;
   548     xx:= hwRound(Gear^.X);
   581     xx:= hwRound(Gear^.X);
   549     yy:= hwRound(Gear^.Y);
   582     yy:= hwRound(Gear^.Y);
   550     end
   583     end
   551 else if GameTicks and $7 = 0 then
   584 else if GameTicks and $7 = 0 then
   552     begin
   585     begin
   558         xx:= hwRound(X);
   591         xx:= hwRound(X);
   559         yy:= hwRound(Y);
   592         yy:= hwRound(Y);
   560         if vobVelocity <> 0 then
   593         if vobVelocity <> 0 then
   561             begin
   594             begin
   562             DirAngle := DirAngle + (Angle / 1250000000);
   595             DirAngle := DirAngle + (Angle / 1250000000);
   563             if DirAngle < 0 then DirAngle := DirAngle + 360
   596             if DirAngle < 0 then
   564             else if 360 < DirAngle then DirAngle := DirAngle - 360;
   597                 DirAngle := DirAngle + 360
       
   598             else if 360 < DirAngle then
       
   599                 DirAngle := DirAngle - 360;
   565             end;
   600             end;
   566 
   601 
   567         inc(Health, 8);
   602         inc(Health, 8);
   568         if longword(Health) > vobFrameTicks then
   603         if longword(Health) > vobFrameTicks then
   569             begin
   604             begin
   570             dec(Health, vobFrameTicks);
   605             dec(Health, vobFrameTicks);
   571             inc(Timer);
   606             inc(Timer);
   572             if Timer = vobFramesCount then Timer:= 0
   607             if Timer = vobFramesCount then
       
   608                 Timer:= 0
   573             end;
   609             end;
   574     // move back to cloud layer
   610     // move back to cloud layer
   575         if yy > cWaterLine then move:= true
   611         if yy > cWaterLine then
   576         else if ((yy and LAND_HEIGHT_MASK) <> 0) or (xx > LAND_WIDTH + 512) or (xx < -512) then move:=true
   612             move:= true
       
   613         else if ((yy and LAND_HEIGHT_MASK) <> 0)
       
   614         or (xx > LAND_WIDTH + 512) or (xx < -512) then
       
   615             move:=true
   577         // Solid pixel encountered
   616         // Solid pixel encountered
   578         else if ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then
   617         else if ((xx and LAND_WIDTH_MASK) = 0) and (Land[yy, xx] <> 0) then
   579             begin
   618             begin
   580             lf:= Land[yy, xx] and (lfObject or lfBasic);
   619             lf:= Land[yy, xx] and (lfObject or lfBasic);
   581             // If there's room below keep falling
   620             // If there's room below keep falling
   614 if draw then
   653 if draw then
   615     with Gear^ do
   654     with Gear^ do
   616         begin
   655         begin
   617         // we've collided with land. draw some stuff and get back into the clouds
   656         // we've collided with land. draw some stuff and get back into the clouds
   618         move:= true;
   657         move:= true;
   619         if (Pos > 20) and ((CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtRope)) then
   658         if (Pos > 20) and ((CurAmmoGear = nil)
       
   659         or (CurAmmoGear^.Kind <> gtRope)) then
   620             begin
   660             begin
   621 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
   661 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
   622             if not gun then
   662             if not gun then
   623                 begin
   663                 begin
   624                 dec(yy,3);
   664                 dec(yy,3);
   642                             end;
   682                             end;
   643                         if Land[yy + py, xx + px] and $FF00 = 0 then
   683                         if Land[yy + py, xx + px] and $FF00 = 0 then
   644                             if gun then
   684                             if gun then
   645                                 begin
   685                                 begin
   646                                 LandDirty[yy div 32, xx div 32]:= 1;
   686                                 LandDirty[yy div 32, xx div 32]:= 1;
   647                                 if LandPixels[ry, rx] = 0 then Land[ly, lx]:=  lfDamaged or lfObject
   687                                 if LandPixels[ry, rx] = 0 then
       
   688                                     Land[ly, lx]:=  lfDamaged or lfObject
   648                                 else Land[ly, lx]:=  lfDamaged or lfBasic
   689                                 else Land[ly, lx]:=  lfDamaged or lfBasic
   649                                 end
   690                                 end
   650                             else Land[ly, lx]:= lf;
   691                             else Land[ly, lx]:= lf;
   651                         if gun then
   692                         if gun then
   652                             LandPixels[ry, rx]:= (cExplosionBorderColor and (not AMask)) or (p^[px] and AMask)
   693                             LandPixels[ry, rx]:= (cExplosionBorderColor and (not AMask)) or (p^[px] and AMask)
   658                 end;
   699                 end;
   659             
   700             
   660             // Why is this here.  For one thing, there's no test on +1 being safe. 
   701             // Why is this here.  For one thing, there's no test on +1 being safe. 
   661             //Land[py, px+1]:= lfBasic;
   702             //Land[py, px+1]:= lfBasic;
   662             
   703             
   663             if allpx then UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w))
   704             if allpx then
       
   705                 UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w))
   664             else
   706             else
   665                 begin
   707                 begin
   666                 UpdateLandTexture(
   708                 UpdateLandTexture(
   667                     max(0, min(LAND_WIDTH, xx)),
   709                     max(0, min(LAND_WIDTH, xx)),
   668                     min(LAND_WIDTH - xx, Pred(s^.w)),
   710                     min(LAND_WIDTH - xx, Pred(s^.w)),
   691 ////////////////////////////////////////////////////////////////////////////////
   733 ////////////////////////////////////////////////////////////////////////////////
   692 procedure doStepGrave(Gear: PGear);
   734 procedure doStepGrave(Gear: PGear);
   693 begin
   735 begin
   694     AllInactive := false;
   736     AllInactive := false;
   695     if Gear^.dY.isNegative then
   737     if Gear^.dY.isNegative then
   696         if TestCollisionY(Gear, -1) then Gear^.dY := _0;
   738         if TestCollisionY(Gear, -1) then
       
   739             Gear^.dY := _0;
   697 
   740 
   698     if not Gear^.dY.isNegative then
   741     if not Gear^.dY.isNegative then
   699         if TestCollisionY(Gear, 1) then
   742         if TestCollisionY(Gear, 1) then
   700         begin
   743         begin
   701             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
   744             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
   702             if Gear^.dY > - _1div1024 then
   745             if Gear^.dY > - _1div1024 then
   703             begin
   746             begin
   704                 Gear^.Active := false;
   747                 Gear^.Active := false;
   705                 exit
   748                 exit
   706             end
   749             end
   707             else if Gear^.dY < - _0_03 then PlaySound(Gear^.ImpactSound)
   750             else if Gear^.dY < - _0_03 then
       
   751                 PlaySound(Gear^.ImpactSound)
   708         end;
   752         end;
   709 
   753 
   710     Gear^.Y := Gear^.Y + Gear^.dY;
   754     Gear^.Y := Gear^.Y + Gear^.dY;
   711     CheckGearDrowning(Gear);
   755     CheckGearDrowning(Gear);
   712     Gear^.dY := Gear^.dY + cGravity
   756     Gear^.dY := Gear^.dY + cGravity
   727     uw := (Gear^.Tag <> 0); // was bee underwater last tick?
   771     uw := (Gear^.Tag <> 0); // was bee underwater last tick?
   728     nuw := (cWaterLine < gy + Gear^.Radius); // is bee underwater now?
   772     nuw := (cWaterLine < gy + Gear^.Radius); // is bee underwater now?
   729 
   773 
   730     // if water entered or left
   774     // if water entered or left
   731     if nuw <> uw then
   775     if nuw <> uw then
   732     begin
   776         begin
   733         AddVisualGear(gX, cWaterLine, vgtSplash);
   777         AddVisualGear(gX, cWaterLine, vgtSplash);
   734         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   778         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   735         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   779         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   736         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   780         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   737         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   781         AddVisualGear(gX - 3 + Random(6), cWaterLine, vgtDroplet);
   738         StopSound(Gear^.SoundChannel);
   782         StopSound(Gear^.SoundChannel);
   739         if nuw then
   783         if nuw then
   740         begin
   784             begin
   741             Gear^.SoundChannel := LoopSound(sndBeeWater);
   785             Gear^.SoundChannel := LoopSound(sndBeeWater);
   742             Gear^.Tag := 1;
   786             Gear^.Tag := 1;
   743         end
   787         end
   744         else
   788         else
   745         begin
   789             begin
   746             Gear^.SoundChannel := LoopSound(sndBee);
   790             Gear^.SoundChannel := LoopSound(sndBee);
   747             Gear^.Tag := 0;
   791             Gear^.Tag := 0;
   748         end;
   792             end;
   749     end;
   793         end;
   750 
   794 
   751 
   795 
   752     if Gear^.Timer = 0 then
   796     if Gear^.Timer = 0 then
   753         Gear^.RenderTimer:= false
   797         Gear^.RenderTimer:= false
   754     else
   798     else
   755     begin
   799         begin
   756         if (GameTicks and $F) = 0 then
   800         if (GameTicks and $F) = 0 then
   757         begin
   801             begin
   758             if (GameTicks and $30) = 0 then
   802             if (GameTicks and $30) = 0 then
   759                 AddVisualGear(gX, gY, vgtBeeTrace);
   803                 AddVisualGear(gX, gY, vgtBeeTrace);
   760             Gear^.dX := Gear^.Elasticity * (Gear^.dX + _0_000064 * (Gear^.Target.X - gX));
   804             Gear^.dX := Gear^.Elasticity * (Gear^.dX + _0_000064 * (Gear^.Target.X - gX));
   761             Gear^.dY := Gear^.Elasticity * (Gear^.dY + _0_000064 * (Gear^.Target.Y - gY));
   805             Gear^.dY := Gear^.Elasticity * (Gear^.dY + _0_000064 * (Gear^.Target.Y - gY));
   762             // make sure new speed isn't higher than original one (which we stored in Friction variable)
   806             // make sure new speed isn't higher than original one (which we stored in Friction variable)
   763             t := Gear^.Friction / Distance(Gear^.dX, Gear^.dY);
   807             t := Gear^.Friction / Distance(Gear^.dX, Gear^.dY);
   764             Gear^.dX := Gear^.dX * t;
   808             Gear^.dX := Gear^.dX * t;
   765             Gear^.dY := Gear^.dY * t;
   809             Gear^.dY := Gear^.dY * t;
   766         end;
   810             end;
   767 
   811 
   768         Gear^.X := Gear^.X + Gear^.dX;
   812         Gear^.X := Gear^.X + Gear^.dX;
   769         Gear^.Y := Gear^.Y + Gear^.dY;
   813         Gear^.Y := Gear^.Y + Gear^.dY;
   770 
   814 
   771     end;
   815         end;
   772 
   816 
   773 
   817 
   774     CheckCollision(Gear);
   818     CheckCollision(Gear);
   775     if ((Gear^.State and gstCollision) <> 0) then
   819     if ((Gear^.State and gstCollision) <> 0) then
   776     begin
   820         begin
   777         StopSound(Gear^.SoundChannel);
   821         StopSound(Gear^.SoundChannel);
   778         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   822         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   779         for i:= 0 to 31 do
   823         for i:= 0 to 31 do
   780             begin
   824             begin
   781             flower:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
   825             flower:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
   783                 with flower^ do
   827                 with flower^ do
   784                     begin
   828                     begin
   785                     Scale:= 0.75;
   829                     Scale:= 0.75;
   786                     dx:= 0.001 * (random(200));
   830                     dx:= 0.001 * (random(200));
   787                     dy:= 0.001 * (random(200));
   831                     dy:= 0.001 * (random(200));
   788                     if random(2) = 0 then dx := -dx;
   832                     if random(2) = 0 then
   789                     if random(2) = 0 then dy := -dy;
   833                         dx := -dx;
       
   834                     if random(2) = 0 then
       
   835                         dy := -dy;
   790                     FrameTicks:= random(250) + 250;
   836                     FrameTicks:= random(250) + 250;
   791                     State:= ord(sprTargetBee);
   837                     State:= ord(sprTargetBee);
   792                     end;
   838                     end;
   793             end;
   839             end;
   794         DeleteGear(Gear);
   840         DeleteGear(Gear);
   795     end;
   841     end;
   796 
   842 
   797     if (Gear^.Timer > 0) then
   843     if (Gear^.Timer > 0) then
   798         dec(Gear^.Timer)
   844         dec(Gear^.Timer)
   799     else
   845     else
   800     begin
   846         begin
   801         if nuw then
   847         if nuw then
   802         begin
   848            begin
   803             StopSound(Gear^.SoundChannel);
   849             StopSound(Gear^.SoundChannel);
   804             CheckGearDrowning(Gear);
   850             CheckGearDrowning(Gear);
   805         end
   851             end
   806         else
   852         else
   807             doStepFallingGear(Gear);
   853             doStepFallingGear(Gear);
   808     end;
   854         end;
   809 end;
   855 end;
   810 
   856 
   811 procedure doStepBee(Gear: PGear);
   857 procedure doStepBee(Gear: PGear);
   812 begin
   858 begin
   813     AllInactive := false;
   859     AllInactive := false;
   814     Gear^.X := Gear^.X + Gear^.dX;
   860     Gear^.X := Gear^.X + Gear^.dX;
   815     Gear^.Y := Gear^.Y + Gear^.dY;
   861     Gear^.Y := Gear^.Y + Gear^.dY;
   816     Gear^.dY := Gear^.dY + cGravity;
   862     Gear^.dY := Gear^.dY + cGravity;
   817     CheckCollision(Gear);
   863     CheckCollision(Gear);
   818     if (Gear^.State and gstCollision) <> 0 then
   864     if (Gear^.State and gstCollision) <> 0 then
   819     begin
   865         begin
   820         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   866         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
   821         DeleteGear(Gear);
   867         DeleteGear(Gear);
   822         exit
   868         exit
   823     end;
   869     end;
   824     dec(Gear^.Timer);
   870     dec(Gear^.Timer);
   825     if Gear^.Timer = 0 then
   871     if Gear^.Timer = 0 then
   826     begin
   872         begin
   827         Gear^.Hedgehog^.Gear^.Message:= Gear^.Hedgehog^.Gear^.Message and (not gmAttack);
   873         Gear^.Hedgehog^.Gear^.Message:= Gear^.Hedgehog^.Gear^.Message and (not gmAttack);
   828         Gear^.Hedgehog^.Gear^.State:= Gear^.Hedgehog^.Gear^.State and (not gstAttacking);
   874         Gear^.Hedgehog^.Gear^.State:= Gear^.Hedgehog^.Gear^.State and (not gstAttacking);
   829         AttackBar:= 0;
   875         AttackBar:= 0;
   830         
   876         
   831         Gear^.SoundChannel := LoopSound(sndBee);
   877         Gear^.SoundChannel := LoopSound(sndBee);
   832         Gear^.Timer := 5000;
   878         Gear^.Timer := 5000;
   833         // save initial speed in otherwise unused Friction variable
   879         // save initial speed in otherwise unused Friction variable
   834         Gear^.Friction := Distance(Gear^.dX, Gear^.dY);
   880         Gear^.Friction := Distance(Gear^.dX, Gear^.dY);
   835         Gear^.doStep := @doStepBeeWork
   881         Gear^.doStep := @doStepBeeWork
   836     end;
   882         end;
   837 end;
   883 end;
   838 
   884 
   839 ////////////////////////////////////////////////////////////////////////////////
   885 ////////////////////////////////////////////////////////////////////////////////
   840 procedure doStepShotIdle(Gear: PGear);
   886 procedure doStepShotIdle(Gear: PGear);
   841 begin
   887 begin
   842     AllInactive := false;
   888     AllInactive := false;
   843     inc(Gear^.Timer);
   889     inc(Gear^.Timer);
   844     if Gear^.Timer > 75 then
   890     if Gear^.Timer > 75 then
   845     begin
   891         begin
   846         DeleteGear(Gear);
   892         DeleteGear(Gear);
   847         AfterAttack
   893         AfterAttack
   848     end
   894         end
   849 end;
   895 end;
   850 
   896 
   851 procedure doStepShotgunShot(Gear: PGear);
   897 procedure doStepShotgunShot(Gear: PGear);
   852 var 
   898 var 
   853     i: LongWord;
   899     i: LongWord;
   854     shell: PVisualGear;
   900     shell: PVisualGear;
   855 begin
   901 begin
   856     AllInactive := false;
   902     AllInactive := false;
   857 
   903 
   858     if ((Gear^.State and gstAnimation) = 0) then
   904     if ((Gear^.State and gstAnimation) = 0) then
   859     begin
   905         begin
   860         dec(Gear^.Timer);
   906         dec(Gear^.Timer);
   861         if Gear^.Timer = 0 then
   907         if Gear^.Timer = 0 then
   862         begin
   908             begin
   863             PlaySound(sndShotgunFire);
   909             PlaySound(sndShotgunFire);
   864             shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell);
   910             shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell);
   865             if shell <> nil then
   911             if shell <> nil then
   866             begin
   912                 begin
   867                 shell^.dX := gear^.dX.QWordValue / -17179869184;
   913                 shell^.dX := gear^.dX.QWordValue / -17179869184;
   868                 shell^.dY := gear^.dY.QWordValue / -17179869184;
   914                 shell^.dY := gear^.dY.QWordValue / -17179869184;
   869                 shell^.Frame := 0
   915                 shell^.Frame := 0
   870             end;
   916                 end;
   871             Gear^.State := Gear^.State or gstAnimation
   917             Gear^.State := Gear^.State or gstAnimation
   872         end;
   918             end;
   873         exit
   919             exit
   874     end
   920         end
   875     else inc(Gear^.Timer);
   921     else
   876 
   922         inc(Gear^.Timer);
   877     i := 200;
   923 
       
   924         i := 200;
   878     repeat
   925     repeat
   879         Gear^.X := Gear^.X + Gear^.dX;
   926         Gear^.X := Gear^.X + Gear^.dX;
   880         Gear^.Y := Gear^.Y + Gear^.dY;
   927         Gear^.Y := Gear^.Y + Gear^.dY;
   881         CheckCollision(Gear);
   928         CheckCollision(Gear);
   882         if (Gear^.State and gstCollision) <> 0 then
   929         if (Gear^.State and gstCollision) <> 0 then
   883         begin
   930             begin
   884             Gear^.X := Gear^.X + Gear^.dX * 8;
   931             Gear^.X := Gear^.X + Gear^.dX * 8;
   885             Gear^.Y := Gear^.Y + Gear^.dY * 8;
   932             Gear^.Y := Gear^.Y + Gear^.dY * 8;
   886             ShotgunShot(Gear);
   933             ShotgunShot(Gear);
   887             Gear^.doStep := @doStepShotIdle;
   934             Gear^.doStep := @doStepShotIdle;
   888             exit
   935             exit
   889         end;
   936             end;
   890 
   937 
   891         CheckGearDrowning(Gear);
   938         CheckGearDrowning(Gear);
   892         if (Gear^.State and gstDrowning) <> 0 then
   939         if (Gear^.State and gstDrowning) <> 0 then
   893         begin
   940             begin
   894             Gear^.doStep := @doStepShotIdle;
   941             Gear^.doStep := @doStepShotIdle;
   895             exit
   942             exit
   896         end;
   943             end;
   897         dec(i)
   944         dec(i)
   898     until i = 0;
   945     until i = 0;
   899     if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0)
   946     if (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0) or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then
   900         then
       
   901         Gear^.doStep := @doStepShotIdle
   947         Gear^.doStep := @doStepShotIdle
   902 end;
   948 end;
   903 
   949 
   904 ////////////////////////////////////////////////////////////////////////////////
   950 ////////////////////////////////////////////////////////////////////////////////
   905 procedure spawnBulletTrail(Bullet: PGear);
   951 procedure spawnBulletTrail(Bullet: PGear);
   917         oy:= Bullet^.Friction;
   963         oy:= Bullet^.Friction;
   918         end;
   964         end;
   919 
   965 
   920         // Bullet trail
   966         // Bullet trail
   921         VGear := AddVisualGear(hwRound(ox), hwRound(oy), vgtLineTrail);
   967         VGear := AddVisualGear(hwRound(ox), hwRound(oy), vgtLineTrail);
       
   968         
   922         if VGear <> nil then
   969         if VGear <> nil then
   923             begin
   970             begin
   924             VGear^.X:= hwFloat2Float(ox);
   971             VGear^.X:= hwFloat2Float(ox);
   925             VGear^.Y:= hwFloat2Float(oy);
   972             VGear^.Y:= hwFloat2Float(oy);
   926             VGear^.dX:= hwFloat2Float(Bullet^.X);
   973             VGear^.dX:= hwFloat2Float(Bullet^.X);
   927             VGear^.dY:= hwFloat2Float(Bullet^.Y);
   974             VGear^.dY:= hwFloat2Float(Bullet^.Y);
   928 
   975 
   929             // reached edge of land. assume infinite beam. Extend it way out past camera
   976             // reached edge of land. assume infinite beam. Extend it way out past camera
   930             if (hwRound(Bullet^.X) and LAND_WIDTH_MASK <> 0)
   977             if (hwRound(Bullet^.X) and LAND_WIDTH_MASK <> 0)
   931                 or (hwRound(Bullet^.Y) and LAND_HEIGHT_MASK <> 0) then
   978             or (hwRound(Bullet^.Y) and LAND_HEIGHT_MASK <> 0) then
   932                     // only extend if not under water
   979                     // only extend if not under water
   933                     if hwRound(Bullet^.Y) < cWaterLine then
   980                     if hwRound(Bullet^.Y) < cWaterLine then
   934                         begin
   981                         begin
   935                         VGear^.dX := VGear^.dX + LAND_WIDTH * (VGear^.dX - VGear^.X);
   982                         VGear^.dX := VGear^.dX + LAND_WIDTH * (VGear^.dX - VGear^.X);
   936                         VGear^.dY := VGear^.dY + LAND_WIDTH * (VGear^.dY - VGear^.Y);
   983                         VGear^.dY := VGear^.dY + LAND_WIDTH * (VGear^.dY - VGear^.Y);
   954     repeat
  1001     repeat
   955         Gear^.X := Gear^.X + Gear^.dX;
  1002         Gear^.X := Gear^.X + Gear^.dX;
   956         Gear^.Y := Gear^.Y + Gear^.dY;
  1003         Gear^.Y := Gear^.Y + Gear^.dY;
   957         x := hwRound(Gear^.X);
  1004         x := hwRound(Gear^.X);
   958         y := hwRound(Gear^.Y);
  1005         y := hwRound(Gear^.Y);
   959         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0)
  1006         
   960            and (Land[y, x] <> 0) then inc(Gear^.Damage);
  1007         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then
       
  1008             inc(Gear^.Damage);
   961         // let's interrupt before a collision to give portals a chance to catch the bullet
  1009         // let's interrupt before a collision to give portals a chance to catch the bullet
   962         if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (Land[y, x] > 255) then
  1010         if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (Land[y, x] > 255) then
   963         begin
  1011             begin
   964             Gear^.Tag := 1;
  1012             Gear^.Tag := 1;
   965             Gear^.Damage := 0;
  1013             Gear^.Damage := 0;
   966             Gear^.X := Gear^.X - Gear^.dX;
  1014             Gear^.X := Gear^.X - Gear^.dX;
   967             Gear^.Y := Gear^.Y - Gear^.dY;
  1015             Gear^.Y := Gear^.Y - Gear^.dY;
   968             CheckGearDrowning(Gear);
  1016             CheckGearDrowning(Gear);
   969             break;
  1017             break;
   970         end
  1018             end
   971         else
  1019         else
   972             Gear^.Tag := 0;
  1020             Gear^.Tag := 0;
   973 
  1021 
   974         if Gear^.Damage > 5 then
  1022         if Gear^.Damage > 5 then
   975             if Gear^.AmmoType = amDEagle then
  1023             if Gear^.AmmoType = amDEagle then
   976                 AmmoShove(Gear, 7, 20)
  1024                 AmmoShove(Gear, 7, 20)
   977         else
  1025         else
   978             AmmoShove(Gear, Gear^.Timer, 20);
  1026             AmmoShove(Gear, Gear^.Timer, 20);
   979         CheckGearDrowning(Gear);
  1027         CheckGearDrowning(Gear);
   980         dec(i)
  1028         dec(i) until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0);
   981     until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0);
       
   982     if Gear^.Damage > 0 then
  1029     if Gear^.Damage > 0 then
   983     begin
  1030         begin
   984         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
  1031         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
   985         dec(Gear^.Health, Gear^.Damage);
  1032         dec(Gear^.Health, Gear^.Damage);
   986         Gear^.Damage := 0
  1033         Gear^.Damage := 0
   987     end;
  1034         end;
   988     if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) then
  1035     if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (cWaterOpacity < $FF)) or (SuddenDeathDmg and (cSDWaterOpacity < $FF))) then
   989     begin
  1036         begin
   990         for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do
  1037         for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do
   991         begin
  1038             begin
   992             if Random(6) = 0 then
  1039             if Random(6) = 0 then
   993                 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble);
  1040                 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble);
   994             Gear^.X := Gear^.X + Gear^.dX;
  1041             Gear^.X := Gear^.X + Gear^.dX;
   995             Gear^.Y := Gear^.Y + Gear^.dY;
  1042             Gear^.Y := Gear^.Y + Gear^.dY;
   996         end;
  1043             end;
   997     end;
  1044         end;
   998 
  1045 
   999     if (Gear^.Health <= 0)
  1046     if (Gear^.Health <= 0)
  1000        or (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0)
  1047         or (hwRound(Gear^.X) and LAND_WIDTH_MASK <> 0)
  1001        or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then
  1048         or (hwRound(Gear^.Y) and LAND_HEIGHT_MASK <> 0) then
  1002     begin
  1049             begin
  1003         if (Gear^.Kind = gtSniperRifleShot) and ((GameFlags and gfLaserSight) = 0) then
  1050             if (Gear^.Kind = gtSniperRifleShot) and ((GameFlags and gfLaserSight) = 0) then
  1004             cLaserSighting := false;
  1051                 cLaserSighting := false;
  1005         if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and
  1052             if (Ammoz[Gear^.AmmoType].Ammo.NumPerTurn <= CurrentHedgehog^.MultiShootAttacks) and ((GameFlags and gfArtillery) = 0) then
  1006            ((GameFlags and gfArtillery) = 0) then cArtillery := false;
  1053                 cArtillery := false;
  1007         
  1054         
  1008         // Bullet Hit
  1055         // Bullet Hit
  1009         if (hwRound(Gear^.X) and LAND_WIDTH_MASK = 0) 
  1056             if (hwRound(Gear^.X) and LAND_WIDTH_MASK = 0) and (hwRound(Gear^.Y) and LAND_HEIGHT_MASK = 0) then
  1010             and (hwRound(Gear^.Y) and LAND_HEIGHT_MASK = 0) then
  1057                 begin
  1011         begin
  1058                 VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit);
  1012             VGear := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBulletHit);
  1059                 if VGear <> nil then
  1013             if VGear <> nil then
  1060                     begin
  1014             begin
  1061                     VGear^.Angle := DxDy2Angle(-Gear^.dX, Gear^.dY);
  1015                 VGear^.Angle := DxDy2Angle(-Gear^.dX, Gear^.dY);
  1062                     end;
  1016             end;
  1063                 end;
  1017         end;
       
  1018        
  1064        
  1019         spawnBulletTrail(Gear);
  1065             spawnBulletTrail(Gear);
  1020         Gear^.doStep := @doStepShotIdle
  1066             Gear^.doStep := @doStepShotIdle
  1021     end;
  1067             end;
  1022 end;
  1068 end;
  1023 
  1069 
  1024 procedure doStepDEagleShot(Gear: PGear);
  1070 procedure doStepDEagleShot(Gear: PGear);
  1025 begin
  1071 begin
  1026     PlaySound(sndGun);
  1072     PlaySound(sndGun);
  1039     HHGear := Gear^.Hedgehog^.Gear;
  1085     HHGear := Gear^.Hedgehog^.Gear;
  1040     HHGear^.State := HHGear^.State or gstNotKickable;
  1086     HHGear^.State := HHGear^.State or gstNotKickable;
  1041     HedgehogChAngle(HHGear);
  1087     HedgehogChAngle(HHGear);
  1042     if not cLaserSighting then
  1088     if not cLaserSighting then
  1043         // game does not have default laser sight. turn it on and give them a chance to aim
  1089         // game does not have default laser sight. turn it on and give them a chance to aim
  1044     begin
  1090         begin
  1045         cLaserSighting := true;
  1091         cLaserSighting := true;
  1046         HHGear^.Message := 0;
  1092         HHGear^.Message := 0;
  1047         if (HHGear^.Angle - 32 >= 0) then dec(HHGear^.Angle,32)
  1093         if (HHGear^.Angle - 32 >= 0) then
  1048     end;
  1094             dec(HHGear^.Angle,32)
       
  1095         end;
  1049 
  1096 
  1050     if (HHGear^.Message and gmAttack) <> 0 then
  1097     if (HHGear^.Message and gmAttack) <> 0 then
  1051     begin
  1098         begin
  1052         shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell);
  1099         shell := AddVisualGear(hwRound(Gear^.x), hwRound(Gear^.y), vgtShell);
  1053         if shell <> nil then
  1100         if shell <> nil then
  1054         begin
  1101             begin
  1055             shell^.dX := gear^.dX.QWordValue / -8589934592;
  1102             shell^.dX := gear^.dX.QWordValue / -8589934592;
  1056             shell^.dY := gear^.dY.QWordValue / -8589934592;
  1103             shell^.dY := gear^.dY.QWordValue / -8589934592;
  1057             shell^.Frame := 1
  1104             shell^.Frame := 1
  1058         end;
  1105             end;
  1059         Gear^.State := Gear^.State or gstAnimation;
  1106         Gear^.State := Gear^.State or gstAnimation;
  1060         Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5;
  1107         Gear^.dX := SignAs(AngleSin(HHGear^.Angle), HHGear^.dX) * _0_5;
  1061         Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5;
  1108         Gear^.dY := -AngleCos(HHGear^.Angle) * _0_5;
  1062         PlaySound(sndGun);
  1109         PlaySound(sndGun);
  1063         // add 3 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just weird angles
  1110         // add 3 initial steps to avoid problem with ammoshove related to calculation of radius + 1 radius as gear widths, and also just weird angles
  1064         Gear^.X := Gear^.X + Gear^.dX * 3;  
  1111         Gear^.X := Gear^.X + Gear^.dX * 3;  
  1065         Gear^.Y := Gear^.Y + Gear^.dY * 3;
  1112         Gear^.Y := Gear^.Y + Gear^.dY * 3;
  1066         Gear^.doStep := @doStepBulletWork;
  1113         Gear^.doStep := @doStepBulletWork;
  1067     end
  1114         end
  1068     else
  1115     else
  1069         if (GameTicks mod 32) = 0 then
  1116         if (GameTicks mod 32) = 0 then
  1070             if (GameTicks mod 4096) < 2048 then
  1117             if (GameTicks mod 4096) < 2048 then
  1071             begin
  1118                 begin
  1072                 if (HHGear^.Angle + 1 <= cMaxAngle) then inc(HHGear^.Angle)
  1119                 if (HHGear^.Angle + 1 <= cMaxAngle) then
  1073             end
  1120                     inc(HHGear^.Angle)
       
  1121                 end
  1074     else
  1122     else
  1075         if (HHGear^.Angle - 1 >= 0) then dec(HHGear^.Angle);
  1123         if (HHGear^.Angle - 1 >= 0) then
       
  1124             dec(HHGear^.Angle);
  1076 
  1125 
  1077     if (TurnTimeLeft > 0) then
  1126     if (TurnTimeLeft > 0) then
  1078         dec(TurnTimeLeft)
  1127         dec(TurnTimeLeft)
  1079     else
  1128     else
  1080     begin
  1129         begin
  1081         DeleteGear(Gear);
  1130         DeleteGear(Gear);
  1082         AfterAttack
  1131         AfterAttack
  1083     end;
  1132         end;
  1084 end;
  1133 end;
  1085 
  1134 
  1086 ////////////////////////////////////////////////////////////////////////////////
  1135 ////////////////////////////////////////////////////////////////////////////////
  1087 procedure doStepActionTimer(Gear: PGear);
  1136 procedure doStepActionTimer(Gear: PGear);
  1088 begin
  1137 begin
  1089     dec(Gear^.Timer);
  1138 dec(Gear^.Timer);
  1090     case Gear^.Kind of 
  1139 case Gear^.Kind of
  1091         gtATStartGame: 
  1140     gtATStartGame: 
  1092     begin
  1141     begin
  1093         AllInactive := false;
  1142         AllInactive := false;
  1094         if Gear^.Timer = 0 then
  1143         if Gear^.Timer = 0 then
  1095         begin
  1144             begin
  1096             AddCaption(trmsg[sidStartFight], cWhiteColor, capgrpGameState);
  1145             AddCaption(trmsg[sidStartFight], cWhiteColor, capgrpGameState);
  1097         end
  1146             end
  1098     end;
  1147     end;
  1099     gtATFinishGame: 
  1148     gtATFinishGame: 
  1100     begin
  1149     begin
  1101         AllInactive := false;
  1150         AllInactive := false;
  1102         if Gear^.Timer = 1000 then
  1151         if Gear^.Timer = 1000 then
  1103         begin
  1152             begin
  1104             ScreenFade := sfToBlack;
  1153             ScreenFade := sfToBlack;
  1105             ScreenFadeValue := 0;
  1154             ScreenFadeValue := 0;
  1106             ScreenFadeSpeed := 1;
  1155             ScreenFadeSpeed := 1;
  1107         end;
  1156             end;
  1108         if Gear^.Timer = 0 then
  1157         if Gear^.Timer = 0 then
  1109         begin
  1158             begin
  1110             SendIPC('N');
  1159             SendIPC('N');
  1111             SendIPC('q');
  1160             SendIPC('q');
  1112             GameState := gsExit
  1161             GameState := gsExit
  1113         end
  1162             end
  1114     end;
  1163     end;
  1115 end;
  1164 end;
  1116 if Gear^.Timer = 0 then DeleteGear(Gear)
  1165 if Gear^.Timer = 0 then
       
  1166     DeleteGear(Gear)
  1117 end;
  1167 end;
  1118 
  1168 
  1119 ////////////////////////////////////////////////////////////////////////////////
  1169 ////////////////////////////////////////////////////////////////////////////////
  1120 procedure doStepPickHammerWork(Gear: PGear);
  1170 procedure doStepPickHammerWork(Gear: PGear);
  1121 var 
  1171 var 
  1123     HHGear: PGear;
  1173     HHGear: PGear;
  1124 begin
  1174 begin
  1125     AllInactive := false;
  1175     AllInactive := false;
  1126     HHGear := Gear^.Hedgehog^.Gear;
  1176     HHGear := Gear^.Hedgehog^.Gear;
  1127     dec(Gear^.Timer);
  1177     dec(Gear^.Timer);
  1128     if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then dec(TurnTimeLeft);
  1178     if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then
  1129     if (TurnTimeLeft = 0) or (Gear^.Timer = 0)or((Gear^.Message and gmDestroy) <> 0)or((HHGear^.State and gstHHDriven) =
  1179         dec(TurnTimeLeft);
  1130        0) then
  1180     if (TurnTimeLeft = 0) or (Gear^.Timer = 0)
       
  1181     or((Gear^.Message and gmDestroy) <> 0)
       
  1182     or((HHGear^.State and gstHHDriven) =0) then
  1131         begin
  1183         begin
  1132         StopSound(Gear^.SoundChannel);
  1184         StopSound(Gear^.SoundChannel);
  1133         DeleteGear(Gear);
  1185         DeleteGear(Gear);
  1134         AfterAttack;
  1186         AfterAttack;
  1135         doStepHedgehogMoving(HHGear);  // for gfInfAttack
  1187         doStepHedgehogMoving(HHGear);  // for gfInfAttack
  1178         if CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y + Gear^.dY + cGravity), $FF00) then
  1230         if CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y + Gear^.dY + cGravity), $FF00) then
  1179             begin
  1231             begin
  1180             Gear^.dY := Gear^.dY + cGravity;
  1232             Gear^.dY := Gear^.dY + cGravity;
  1181             Gear^.Y := Gear^.Y + Gear^.dY
  1233             Gear^.Y := Gear^.Y + Gear^.dY
  1182             end;
  1234             end;
  1183         if hwRound(Gear^.Y) > cWaterLine then Gear^.Timer := 1
  1235         if hwRound(Gear^.Y) > cWaterLine then
       
  1236             Gear^.Timer := 1
  1184         end;
  1237         end;
  1185 
  1238 
  1186     Gear^.X := Gear^.X + HHGear^.dX;
  1239     Gear^.X := Gear^.X + HHGear^.dX;
  1187     if CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y)-cHHRadius, $FF00) then
  1240     if CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y)-cHHRadius, $FF00) then
  1188         begin
  1241         begin
  1189         HHGear^.X := Gear^.X;
  1242         HHGear^.X := Gear^.X;
  1190         HHGear^.Y := Gear^.Y - int2hwFloat(cHHRadius)
  1243         HHGear^.Y := Gear^.Y - int2hwFloat(cHHRadius)
  1191         end;
  1244         end;
  1192 
  1245 
  1193     if (Gear^.Message and gmAttack) <> 0 then
  1246     if (Gear^.Message and gmAttack) <> 0 then
  1194         if (Gear^.State and gsttmpFlag) <> 0 then Gear^.Timer := 1
  1247         if (Gear^.State and gsttmpFlag) <> 0 then
       
  1248             Gear^.Timer := 1
       
  1249     else //there would be a mistake.
  1195     else
  1250     else
       
  1251         if (Gear^.State and gsttmpFlag) = 0 then
       
  1252             Gear^.State := Gear^.State or gsttmpFlag;
       
  1253     if ((Gear^.Message and gmLeft) <> 0) then
       
  1254         Gear^.dX := - _0_3
  1196     else
  1255     else
  1197         if (Gear^.State and gsttmpFlag) = 0 then Gear^.State := Gear^.State or gsttmpFlag;
  1256         if ((Gear^.Message and gmRight) <> 0) then
  1198     if ((Gear^.Message and gmLeft) <> 0) then Gear^.dX := - _0_3
  1257             Gear^.dX := _0_3
  1199     else
       
  1200         if ((Gear^.Message and gmRight) <> 0) then Gear^.dX := _0_3
       
  1201     else Gear^.dX := _0;
  1258     else Gear^.dX := _0;
  1202 end;
  1259 end;
  1203 
  1260 
  1204 procedure doStepPickHammer(Gear: PGear);
  1261 procedure doStepPickHammer(Gear: PGear);
  1205 var 
  1262 var 
  1210     i := 0;
  1267     i := 0;
  1211     HHGear := Gear^.Hedgehog^.Gear;
  1268     HHGear := Gear^.Hedgehog^.Gear;
  1212 
  1269 
  1213     y := hwRound(Gear^.Y) - cHHRadius * 2;
  1270     y := hwRound(Gear^.Y) - cHHRadius * 2;
  1214     while y < hwRound(Gear^.Y) do
  1271     while y < hwRound(Gear^.Y) do
  1215     begin
  1272         begin
  1216         ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
  1273         ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
  1217         ar[i].Right := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
  1274         ar[i].Right := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
  1218         inc(y, 2);
  1275         inc(y, 2);
  1219         inc(i)
  1276         inc(i)
  1220     end;
  1277         end;
  1221 
  1278 
  1222     DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius * 2, 2, Pred(i));
  1279     DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius * 2, 2, Pred(i));
  1223     Gear^.dY := HHGear^.dY;
  1280     Gear^.dY := HHGear^.dY;
  1224     DeleteCI(HHGear);
  1281     DeleteCI(HHGear);
  1225 
  1282 
  1238     b: boolean;
  1295     b: boolean;
  1239     prevX: LongInt;
  1296     prevX: LongInt;
  1240 begin
  1297 begin
  1241     AllInactive := false;
  1298     AllInactive := false;
  1242     dec(Gear^.Timer);
  1299     dec(Gear^.Timer);
  1243     if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then dec(TurnTimeLeft);
  1300     if ((GameFlags and gfInfAttack) <> 0) and (TurnTimeLeft > 0) then
       
  1301         dec(TurnTimeLeft);
  1244     
  1302     
  1245     HHGear := Gear^.Hedgehog^.Gear;
  1303     HHGear := Gear^.Hedgehog^.Gear;
  1246 
  1304 
  1247     HedgehogChAngle(HHGear);
  1305     HedgehogChAngle(HHGear);
  1248 
  1306 
  1257         end;
  1315         end;
  1258 
  1316 
  1259     if ((HHGear^.State and gstMoving) <> 0) then
  1317     if ((HHGear^.State and gstMoving) <> 0) then
  1260         begin
  1318         begin
  1261         doStepHedgehogMoving(HHGear);
  1319         doStepHedgehogMoving(HHGear);
  1262         if (HHGear^.State and gstHHDriven) = 0 then Gear^.Timer := 0
  1320         if (HHGear^.State and gstHHDriven) = 0 then
       
  1321             Gear^.Timer := 0
  1263         end;
  1322         end;
  1264 
  1323 
  1265     if Gear^.Timer mod cHHStepTicks = 0 then
  1324     if Gear^.Timer mod cHHStepTicks = 0 then
  1266         begin
  1325         begin
  1267         b := true;
  1326         b := true;
  1288 
  1347 
  1289         inc(BTSteps);
  1348         inc(BTSteps);
  1290         if BTSteps = 7 then
  1349         if BTSteps = 7 then
  1291             begin
  1350             begin
  1292             BTSteps := 0;
  1351             BTSteps := 0;
  1293             if CheckLandValue(hwRound(HHGear^.X + Gear^.dX * (cHHRadius + cBlowTorchC) + SignAs(_6,
  1352             if CheckLandValue(hwRound(HHGear^.X + Gear^.dX * (cHHRadius + cBlowTorchC) + SignAs(_6,Gear^.dX)), hwRound(HHGear^.Y + Gear^.dY * (cHHRadius + cBlowTorchC)),lfIndestructible) then
  1294                Gear^.dX)), hwRound(HHGear^.Y + Gear^.dY * (cHHRadius + cBlowTorchC)),
       
  1295                lfIndestructible) then
       
  1296                 begin
  1353                 begin
  1297                 Gear^.X := HHGear^.X + Gear^.dX * (cHHRadius + cBlowTorchC);
  1354                 Gear^.X := HHGear^.X + Gear^.dX * (cHHRadius + cBlowTorchC);
  1298                 Gear^.Y := HHGear^.Y + Gear^.dY * (cHHRadius + cBlowTorchC);
  1355                 Gear^.Y := HHGear^.Y + Gear^.dY * (cHHRadius + cBlowTorchC);
  1299                 end;
  1356                 end;
  1300             HHGear^.State := HHGear^.State or gstNoDamage;
  1357             HHGear^.State := HHGear^.State or gstNoDamage;
  1310         ((hwAbs(Gear^.dX) / (hwAbs(Gear^.dX) + hwAbs(Gear^.dY))) * _0_5 * 7),
  1367         ((hwAbs(Gear^.dX) / (hwAbs(Gear^.dX) + hwAbs(Gear^.dY))) * _0_5 * 7),
  1311         Gear^.dX, Gear^.dY,
  1368         Gear^.dX, Gear^.dY,
  1312         cHHStepTicks, cHHRadius * 2 + 7);
  1369         cHHStepTicks, cHHRadius * 2 + 7);
  1313     end;
  1370     end;
  1314 
  1371 
  1315     if (TurnTimeLeft = 0) or (Gear^.Timer = 0) or ((HHGear^.Message and gmAttack) <> 0) then
  1372     if (TurnTimeLeft = 0) or (Gear^.Timer = 0)
       
  1373     or ((HHGear^.Message and gmAttack) <> 0) then
  1316         begin
  1374         begin
  1317         HHGear^.Message := 0;
  1375         HHGear^.Message := 0;
  1318         HHGear^.State := HHGear^.State and (not gstNotKickable);
  1376         HHGear^.State := HHGear^.State and (not gstNotKickable);
  1319         DeleteGear(Gear);
  1377         DeleteGear(Gear);
  1320         AfterAttack
  1378         AfterAttack
  1342 var 
  1400 var 
  1343     HHGear: PGear;
  1401     HHGear: PGear;
  1344 begin
  1402 begin
  1345     HHGear := Gear^.Hedgehog^.Gear;
  1403     HHGear := Gear^.Hedgehog^.Gear;
  1346     if ((HHGear^.State and gstHHDriven) = 0)
  1404     if ((HHGear^.State and gstHHDriven) = 0)
  1347        or (CheckGearDrowning(HHGear))
  1405     or (CheckGearDrowning(HHGear))
  1348        or (TestCollisionYwithGear(HHGear, 1) <> 0) then
  1406     or (TestCollisionYwithGear(HHGear, 1) <> 0) then
  1349     begin
  1407         begin
  1350         DeleteGear(Gear);
  1408         DeleteGear(Gear);
  1351         isCursorVisible := false;
  1409         isCursorVisible := false;
  1352         ApplyAmmoChanges(HHGear^.Hedgehog^);
  1410         ApplyAmmoChanges(HHGear^.Hedgehog^);
  1353         exit
  1411         exit
  1354     end;
  1412         end;
  1355 
  1413 
  1356     HedgehogChAngle(HHGear);
  1414     HedgehogChAngle(HHGear);
  1357 
  1415 
  1358     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
  1416     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
  1359 
  1417         SetLittle(HHGear^.dX);
  1360     if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then HHGear^.dY := _0;
  1418 
       
  1419     if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then
       
  1420         HHGear^.dY := _0;
  1361     HHGear^.X := HHGear^.X + HHGear^.dX;
  1421     HHGear^.X := HHGear^.X + HHGear^.dX;
  1362     HHGear^.Y := HHGear^.Y + HHGear^.dY;
  1422     HHGear^.Y := HHGear^.Y + HHGear^.dY;
  1363     HHGear^.dY := HHGear^.dY + cGravity;
  1423     HHGear^.dY := HHGear^.dY + cGravity;
  1364     if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
  1424     
       
  1425     if (GameFlags and gfMoreWind) <> 0 then
       
  1426         HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density;
  1365 
  1427 
  1366     if (Gear^.Message and gmAttack) <> 0 then
  1428     if (Gear^.Message and gmAttack) <> 0 then
  1367         begin
  1429         begin
  1368         Gear^.X := HHGear^.X;
  1430         Gear^.X := HHGear^.X;
  1369         Gear^.Y := HHGear^.Y;
  1431         Gear^.Y := HHGear^.Y;
  1380 end;
  1442 end;
  1381 
  1443 
  1382 procedure RopeDeleteMe(Gear, HHGear: PGear);
  1444 procedure RopeDeleteMe(Gear, HHGear: PGear);
  1383 begin
  1445 begin
  1384     with HHGear^ do
  1446     with HHGear^ do
  1385     begin
  1447         begin
  1386         Message := Message and (not gmAttack);
  1448         Message := Message and (not gmAttack);
  1387         State := (State or gstMoving) and (not gstWinner);
  1449         State := (State or gstMoving) and (not gstWinner);
  1388     end;
  1450         end;
  1389     DeleteGear(Gear)
  1451     DeleteGear(Gear)
  1390 end;
  1452 end;
  1391 
  1453 
  1392 procedure RopeWaitCollision(Gear, HHGear: PGear);
  1454 procedure RopeWaitCollision(Gear, HHGear: PGear);
  1393 begin
  1455 begin
  1394     with HHGear^ do
  1456     with HHGear^ do
  1395     begin
  1457         begin
  1396         Message := Message and (not gmAttack);
  1458         Message := Message and (not gmAttack);
  1397         State := State or gstMoving;
  1459         State := State or gstMoving;
  1398     end;
  1460         end;
  1399     RopePoints.Count := 0;
  1461     RopePoints.Count := 0;
  1400     Gear^.Elasticity := _0;
  1462     Gear^.Elasticity := _0;
  1401     Gear^.doStep := @doStepRopeAfterAttack
  1463     Gear^.doStep := @doStepRopeAfterAttack
  1402 end;
  1464 end;
  1403 
  1465 
  1465     tx := HHGear^.X;
  1527     tx := HHGear^.X;
  1466     ty := HHGear^.Y;
  1528     ty := HHGear^.Y;
  1467 
  1529 
  1468     if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
  1530     if ((Gear^.Message and gmDown) <> 0) and (Gear^.Elasticity < Gear^.Friction) then
  1469         if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
  1531         if not (TestCollisionXwithGear(HHGear, hwSign(ropeDx))
  1470            or (TestCollisionYwithGear(HHGear, hwSign(ropeDy)) <> 0)) then
  1532         or (TestCollisionYwithGear(HHGear, hwSign(ropeDy)) <> 0)) then
  1471             Gear^.Elasticity := Gear^.Elasticity + _0_3;
  1533             Gear^.Elasticity := Gear^.Elasticity + _0_3;
  1472 
  1534 
  1473     if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
  1535     if ((Gear^.Message and gmUp) <> 0) and (Gear^.Elasticity > _30) then
  1474         if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
  1536         if not (TestCollisionXwithGear(HHGear, -hwSign(ropeDx))
  1475            or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
  1537         or (TestCollisionYwithGear(HHGear, -hwSign(ropeDy)) <> 0)) then
  1476             Gear^.Elasticity := Gear^.Elasticity - _0_3;
  1538             Gear^.Elasticity := Gear^.Elasticity - _0_3;
  1477 
  1539 
  1478     HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
  1540     HHGear^.X := Gear^.X + mdX * Gear^.Elasticity;
  1479     HHGear^.Y := Gear^.Y + mdY * Gear^.Elasticity;
  1541     HHGear^.Y := Gear^.Y + mdY * Gear^.Elasticity;
  1480 
  1542 
  1505 
  1567 
  1506             with RopePoints.ar[RopePoints.Count] do
  1568             with RopePoints.ar[RopePoints.Count] do
  1507                 begin
  1569                 begin
  1508                 X := Gear^.X;
  1570                 X := Gear^.X;
  1509                 Y := Gear^.Y;
  1571                 Y := Gear^.Y;
  1510                 if RopePoints.Count = 0 then RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
  1572                 if RopePoints.Count = 0 then
       
  1573                     RopePoints.HookAngle := DxDy2Angle(Gear^.dY, Gear^.dX);
  1511                 b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
  1574                 b := (nx * HHGear^.dY) > (ny * HHGear^.dX);
  1512                 dLen := len
  1575                 dLen := len
  1513                 end;
  1576                 end;
       
  1577                 
  1514             with RopePoints.rounded[RopePoints.Count] do
  1578             with RopePoints.rounded[RopePoints.Count] do
  1515                 begin
  1579                 begin
  1516                 X := hwRound(Gear^.X);
  1580                 X := hwRound(Gear^.X);
  1517                 Y := hwRound(Gear^.Y);
  1581                 Y := hwRound(Gear^.Y);
  1518                 end;
  1582                 end;
  1568         begin
  1632         begin
  1569         HHGear^.dY := -_0_6 * HHGear^.dY;
  1633         HHGear^.dY := -_0_6 * HHGear^.dY;
  1570         haveCollision := true
  1634         haveCollision := true
  1571         end;
  1635         end;
  1572 
  1636 
  1573     if haveCollision
  1637     if haveCollision and (Gear^.Message and (gmLeft or gmRight) <> 0) and (Gear^.Message and (gmUp or gmDown) <> 0) then
  1574        and (Gear^.Message and (gmLeft or gmRight) <> 0)
       
  1575        and (Gear^.Message and (gmUp or gmDown) <> 0) then
       
  1576         begin
  1638         begin
  1577         HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _0_2, HHGear^.dX);
  1639         HHGear^.dX := SignAs(hwAbs(HHGear^.dX) + _0_2, HHGear^.dX);
  1578         HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _0_2, HHGear^.dY)
  1640         HHGear^.dY := SignAs(hwAbs(HHGear^.dY) + _0_2, HHGear^.dY)
  1579         end;
  1641         end;
  1580 
  1642 
  1640 end;
  1702 end;
  1641 
  1703 
  1642 procedure RopeRemoveFromAmmo(Gear, HHGear: PGear);
  1704 procedure RopeRemoveFromAmmo(Gear, HHGear: PGear);
  1643 begin
  1705 begin
  1644     if (Gear^.State and gstAttacked) = 0 then
  1706     if (Gear^.State and gstAttacked) = 0 then
  1645     begin
  1707         begin
  1646         OnUsedAmmo(HHGear^.Hedgehog^);
  1708         OnUsedAmmo(HHGear^.Hedgehog^);
  1647         Gear^.State := Gear^.State or gstAttacked
  1709         Gear^.State := Gear^.State or gstAttacked
  1648     end;
  1710         end;
  1649     ApplyAmmoChanges(HHGear^.Hedgehog^)
  1711     ApplyAmmoChanges(HHGear^.Hedgehog^)
  1650 end;
  1712 end;
  1651 
  1713 
  1652 procedure doStepRopeAttach(Gear: PGear);
  1714 procedure doStepRopeAttach(Gear: PGear);
  1653 var 
  1715 var 
  1661     HHGear := Gear^.Hedgehog^.Gear;
  1723     HHGear := Gear^.Hedgehog^.Gear;
  1662     DeleteCI(HHGear);
  1724     DeleteCI(HHGear);
  1663 
  1725 
  1664     if (HHGear^.State and gstMoving) <> 0 then
  1726     if (HHGear^.State and gstMoving) <> 0 then
  1665         begin
  1727         begin
  1666         if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then SetLittle(HHGear^.dX);
  1728         if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
  1667         if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then HHGear^.dY := _0;
  1729             SetLittle(HHGear^.dX);
       
  1730         if HHGear^.dY.isNegative and (TestCollisionYwithGear(HHGear, -1) <> 0) then
       
  1731             HHGear^.dY := _0;
  1668 
  1732 
  1669         HHGear^.X := HHGear^.X + HHGear^.dX;
  1733         HHGear^.X := HHGear^.X + HHGear^.dX;
  1670         Gear^.X := Gear^.X + HHGear^.dX;
  1734         Gear^.X := Gear^.X + HHGear^.dX;
  1671 
  1735 
  1672         if TestCollisionYwithGear(HHGear, 1) <> 0 then
  1736         if TestCollisionYwithGear(HHGear, 1) <> 0 then
  1678         else
  1742         else
  1679             begin
  1743             begin
  1680             HHGear^.Y := HHGear^.Y + HHGear^.dY;
  1744             HHGear^.Y := HHGear^.Y + HHGear^.dY;
  1681             Gear^.Y := Gear^.Y + HHGear^.dY;
  1745             Gear^.Y := Gear^.Y + HHGear^.dY;
  1682             HHGear^.dY := HHGear^.dY + cGravity;
  1746             HHGear^.dY := HHGear^.dY + cGravity;
  1683             if (GameFlags and gfMoreWind) <> 0 then HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density
  1747             if (GameFlags and gfMoreWind) <> 0 then
       
  1748                 HHGear^.dX := HHGear^.dX + cWindSpeed / HHGear^.Density
  1684             end;
  1749             end;
  1685 
  1750 
  1686         tt := Gear^.Elasticity;
  1751         tt := Gear^.Elasticity;
  1687         tx := _0;
  1752         tx := _0;
  1688         ty := _0;
  1753         ty := _0;
  1731 
  1796 
  1732         exit
  1797         exit
  1733         end;
  1798         end;
  1734 
  1799 
  1735     if (Gear^.Elasticity > Gear^.Friction)
  1800     if (Gear^.Elasticity > Gear^.Friction)
  1736        or ((Gear^.Message and gmAttack) = 0)
  1801         or ((Gear^.Message and gmAttack) = 0)
  1737        or ((HHGear^.State and gstHHDriven) = 0)
  1802         or ((HHGear^.State and gstHHDriven) = 0)
  1738        or (HHGear^.Damage > 0) then
  1803         or (HHGear^.Damage > 0) then
  1739         begin
  1804             begin
  1740         with Gear^.Hedgehog^.Gear^ do
  1805             with Gear^.Hedgehog^.Gear^ do
  1741             begin
  1806                 begin
  1742             State := State and (not gstAttacking);
  1807                 State := State and (not gstAttacking);
  1743             Message := Message and (not gmAttack)
  1808                 Message := Message and (not gmAttack)
  1744             end;
  1809                 end;
  1745         DeleteGear(Gear)
  1810         DeleteGear(Gear)
  1746         end;
  1811         end;
  1747     CheckGearDrowning(HHGear)
  1812     CheckGearDrowning(HHGear)
  1748 end;
  1813 end;
  1749 
  1814 
  1758 ////////////////////////////////////////////////////////////////////////////////
  1823 ////////////////////////////////////////////////////////////////////////////////
  1759 procedure doStepMine(Gear: PGear);
  1824 procedure doStepMine(Gear: PGear);
  1760 var vg: PVisualGear;
  1825 var vg: PVisualGear;
  1761 begin
  1826 begin
  1762     if (Gear^.State and gstMoving) <> 0 then
  1827     if (Gear^.State and gstMoving) <> 0 then
  1763     begin
  1828         begin
  1764         DeleteCI(Gear);
  1829         DeleteCI(Gear);
  1765         doStepFallingGear(Gear);
  1830         doStepFallingGear(Gear);
  1766         if (Gear^.State and gstMoving) = 0 then
  1831         if (Gear^.State and gstMoving) = 0 then
  1767         begin
  1832             begin
  1768             AddGearCI(Gear);
  1833             AddGearCI(Gear);
  1769             Gear^.dX := _0;
  1834             Gear^.dX := _0;
  1770             Gear^.dY := _0
  1835             Gear^.dY := _0
  1771         end;
  1836             end;
  1772         CalcRotationDirAngle(Gear);
  1837         CalcRotationDirAngle(Gear);
  1773         AllInactive := false
  1838         AllInactive := false
  1774     end
  1839     end
  1775     else
  1840     else
  1776         if ((GameTicks and $3F) = 25) then
  1841         if ((GameTicks and $3F) = 25) then
  1777             doStepFallingGear(Gear);
  1842             doStepFallingGear(Gear);
  1778     if (Gear^.Health = 0) then
  1843     if (Gear^.Health = 0) then
  1779         begin
  1844         begin
  1780             if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1845             if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1781                 inc(Gear^.Damage, hwRound(Gear^.dY * _70))
  1846                 inc(Gear^.Damage, hwRound(Gear^.dY * _70))
       
  1847                 
  1782             else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1848             else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1783                  inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  1849                 inc(Gear^.Damage, hwRound(Gear^.dX * _70))
       
  1850                 
  1784             else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1851             else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1785                  inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  1852                 inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
       
  1853                 
  1786             else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
  1854             else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
  1787                  inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
  1855                 inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
  1788         
  1856         
  1789         if ((GameTicks and $FF) = 0) and (Gear^.Damage > random(30)) then
  1857         if ((GameTicks and $FF) = 0) and (Gear^.Damage > random(30)) then
  1790             begin
  1858                 begin
  1791             vg:= AddVisualGear(hwRound(Gear^.X) - 4  + Random(8), hwRound(Gear^.Y) - 4 - Random(4), vgtSmoke);
  1859                 vg:= AddVisualGear(hwRound(Gear^.X) - 4  + Random(8), hwRound(Gear^.Y) - 4 - Random(4), vgtSmoke);
  1792             if vg <> nil then vg^.Scale:= 0.5
  1860                 if vg <> nil then
  1793             end;
  1861                     vg^.Scale:= 0.5
       
  1862                 end;
  1794 
  1863 
  1795         if (Gear^.Damage > 35) then
  1864         if (Gear^.Damage > 35) then
  1796             begin
  1865             begin
  1797             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  1866             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  1798             DeleteGear(Gear);
  1867             DeleteGear(Gear);
  1802 
  1871 
  1803     if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
  1872     if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
  1804         if ((Gear^.State and gstAttacking) = 0) then
  1873         if ((Gear^.State and gstAttacking) = 0) then
  1805             begin
  1874             begin
  1806             if ((GameTicks and $1F) = 0) then
  1875             if ((GameTicks and $1F) = 0) then
  1807                 if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then Gear^.State := Gear^.State or
  1876                 if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then
  1808                                                                                       gstAttacking
  1877                     Gear^.State := Gear^.State or gstAttacking
  1809             end
  1878             end
  1810         else // gstAttacking <> 0
  1879         else // gstAttacking <> 0
  1811             begin
  1880             begin
  1812             AllInactive := false;
  1881             AllInactive := false;
  1813             if (Gear^.Timer and $FF) = 0 then PlaySound(sndMineTick);
  1882             if (Gear^.Timer and $FF) = 0 then
       
  1883                 PlaySound(sndMineTick);
  1814             if Gear^.Timer = 0 then
  1884             if Gear^.Timer = 0 then
  1815                 begin
  1885                 begin
  1816                 if ((Gear^.State and gstWait) <> 0) or
  1886                 if ((Gear^.State and gstWait) <> 0)
  1817                    (cMineDudPercent = 0) or
  1887                 or (cMineDudPercent = 0)
  1818                    (getRandom(100) > cMineDudPercent) then
  1888                 or (getRandom(100) > cMineDudPercent) then
  1819                     begin
  1889                     begin
  1820                     doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  1890                     doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  1821                     DeleteGear(Gear)
  1891                     DeleteGear(Gear)
  1822                     end
  1892                     end
  1823                 else
  1893                 else
  1824                     begin
  1894                     begin
  1825                     vg:= AddVisualGear(hwRound(Gear^.X) - 4  + Random(8), hwRound(Gear^.Y) - 4 - Random(4), vgtSmoke);
  1895                     vg:= AddVisualGear(hwRound(Gear^.X) - 4  + Random(8), hwRound(Gear^.Y) - 4 - Random(4), vgtSmoke);
  1826                     if vg <> nil then vg^.Scale:= 0.5;
  1896                     if vg <> nil then
       
  1897                         vg^.Scale:= 0.5;
  1827                     PlaySound(sndVaporize);
  1898                     PlaySound(sndVaporize);
  1828                     Gear^.Health := 0;
  1899                     Gear^.Health := 0;
  1829                     Gear^.Damage := 0;
  1900                     Gear^.Damage := 0;
  1830                     Gear^.State := Gear^.State and (not gstAttacking)
  1901                     Gear^.State := Gear^.State and (not gstAttacking)
  1831                     end;
  1902                     end;
  1832                 exit
  1903                 exit
  1833                 end;
  1904                 end;
  1834             dec(Gear^.Timer);
  1905             dec(Gear^.Timer);
  1835             end
  1906             end
  1836     else // gsttmpFlag = 0
  1907     else // gsttmpFlag = 0
  1837         if (TurnTimeLeft = 0) or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) or (Gear^.Hedgehog^.Gear = nil) then Gear^.State := Gear^.State or gsttmpFlag;
  1908         if (TurnTimeLeft = 0)
       
  1909         or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime))
       
  1910         or (Gear^.Hedgehog^.Gear = nil) then
       
  1911             Gear^.State := Gear^.State or gsttmpFlag;
  1838 end;
  1912 end;
  1839 
  1913 
  1840 ////////////////////////////////////////////////////////////////////////////////
  1914 ////////////////////////////////////////////////////////////////////////////////
  1841 procedure doStepSMine(Gear: PGear);
  1915 procedure doStepSMine(Gear: PGear);
  1842 begin
  1916 begin
  1843     // TODO: do real calculation?
  1917     // TODO: do real calculation?
  1844     if TestCollisionXwithGear(Gear, 2) 
  1918     if TestCollisionXwithGear(Gear, 2) 
  1845         or (TestCollisionYwithGear(Gear, -2) <> 0) 
  1919     or (TestCollisionYwithGear(Gear, -2) <> 0) 
  1846         or TestCollisionXwithGear(Gear, -2) 
  1920     or TestCollisionXwithGear(Gear, -2) 
  1847         or (TestCollisionYwithGear(Gear, 2) <> 0) then
  1921     or (TestCollisionYwithGear(Gear, 2) <> 0) then
  1848     begin
  1922         begin
  1849         if (hwAbs(Gear^.dX) > _0) or (hwAbs(Gear^.dY) > _0) then
  1923         if (hwAbs(Gear^.dX) > _0) or (hwAbs(Gear^.dY) > _0) then
  1850         begin
  1924             begin
  1851             PlaySound(sndRopeAttach);
  1925             PlaySound(sndRopeAttach);
  1852             Gear^.dX:= _0;
  1926             Gear^.dX:= _0;
  1853             Gear^.dY:= _0;
  1927             Gear^.dY:= _0;
  1854             AddGearCI(Gear);
  1928             AddGearCI(Gear);
  1855         end;
  1929             end;
  1856     end
  1930         end
  1857     else
  1931     else
  1858     begin
  1932         begin
  1859         DeleteCI(Gear);
  1933         DeleteCI(Gear);
  1860         doStepFallingGear(Gear);
  1934         doStepFallingGear(Gear);
  1861         AllInactive := false;
  1935         AllInactive := false;
  1862         CalcRotationDirAngle(Gear);
  1936         CalcRotationDirAngle(Gear);
  1863     end;
  1937         end;
  1864 
  1938 
  1865     if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
  1939     if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
  1866     begin
  1940         begin
  1867         if ((Gear^.State and gstAttacking) = 0) then
  1941         if ((Gear^.State and gstAttacking) = 0) then
  1868         begin
  1942             begin
  1869             if ((GameTicks and $1F) = 0) then
  1943             if ((GameTicks and $1F) = 0) then
  1870                 if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then Gear^.State := Gear^.State or
  1944                 if CheckGearNear(Gear, gtHedgehog, 46, 32) <> nil then
  1871                                                                                       gstAttacking
  1945                     Gear^.State := Gear^.State or gstAttacking
  1872         end
  1946             end
  1873         else // gstAttacking <> 0
  1947         else // gstAttacking <> 0
  1874         begin
  1948         begin
  1875             AllInactive := false;
  1949             AllInactive := false;
  1876             if Gear^.Timer = 0 then
  1950             if Gear^.Timer = 0 then
  1877             begin
  1951                 begin
  1878                 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  1952                 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  1879                 DeleteGear(Gear);
  1953                 DeleteGear(Gear);
  1880                 exit
  1954                 exit
  1881             end else
  1955             end else
  1882                 if (Gear^.Timer and $FF) = 0 then PlaySound(sndMineTick);
  1956                 if (Gear^.Timer and $FF) = 0 then
       
  1957                     PlaySound(sndMineTick);
  1883 
  1958 
  1884             dec(Gear^.Timer);
  1959             dec(Gear^.Timer);
       
  1960                 end
  1885         end
  1961         end
  1886     end
       
  1887     else // gsttmpFlag = 0
  1962     else // gsttmpFlag = 0
  1888         if (TurnTimeLeft = 0) or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) or (Gear^.Hedgehog^.Gear = nil) then Gear^.State := Gear^.State or gsttmpFlag;
  1963         if (TurnTimeLeft = 0)
       
  1964         or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime))
       
  1965         or (Gear^.Hedgehog^.Gear = nil) then
       
  1966             Gear^.State := Gear^.State or gsttmpFlag;
  1889 end;
  1967 end;
  1890 
  1968 
  1891 ////////////////////////////////////////////////////////////////////////////////
  1969 ////////////////////////////////////////////////////////////////////////////////
  1892 procedure doStepDynamite(Gear: PGear);
  1970 procedure doStepDynamite(Gear: PGear);
  1893 begin
  1971 begin
  1894     doStepFallingGear(Gear);
  1972     doStepFallingGear(Gear);
  1895     AllInactive := false;
  1973     AllInactive := false;
  1896     if Gear^.Timer mod 166 = 0 then inc(Gear^.Tag);
  1974     if Gear^.Timer mod 166 = 0 then
       
  1975         inc(Gear^.Tag);
  1897     if Gear^.Timer = 1000 then // might need better timing
  1976     if Gear^.Timer = 1000 then // might need better timing
  1898         makeHogsWorry(Gear^.X, Gear^.Y, 75);
  1977         makeHogsWorry(Gear^.X, Gear^.Y, 75);
  1899     if Gear^.Timer = 0 then
  1978     if Gear^.Timer = 0 then
  1900     begin
  1979         begin
  1901         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 75, Gear^.Hedgehog, EXPLAutoSound);
  1980         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 75, Gear^.Hedgehog, EXPLAutoSound);
  1902         DeleteGear(Gear);
  1981         DeleteGear(Gear);
  1903         exit
  1982         exit
  1904     end;
  1983         end;
  1905     dec(Gear^.Timer);
  1984     dec(Gear^.Timer);
  1906 end;
  1985 end;
  1907 
  1986 
  1908 ///////////////////////////////////////////////////////////////////////////////
  1987 ///////////////////////////////////////////////////////////////////////////////
  1909 
  1988 
  1915 procedure doStepRollingBarrel(Gear: PGear);
  1994 procedure doStepRollingBarrel(Gear: PGear);
  1916 var 
  1995 var 
  1917     i: LongInt;
  1996     i: LongInt;
  1918     particle: PVisualGear;
  1997     particle: PVisualGear;
  1919 begin
  1998 begin
  1920     if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then SetLittle(Gear^.dY);
  1999     if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then
       
  2000         SetLittle(Gear^.dY);
  1921     Gear^.State := Gear^.State or gstAnimation;
  2001     Gear^.State := Gear^.State or gstAnimation;
  1922     if ((Gear^.dX.QWordValue <> 0) or (Gear^.dY.QWordValue <> 0))  then
  2002     
  1923     begin
  2003     if ((Gear^.dX.QWordValue <> 0)
       
  2004     or (Gear^.dY.QWordValue <> 0))  then
       
  2005         begin
  1924         DeleteCI(Gear);
  2006         DeleteCI(Gear);
  1925         AllInactive := false;
  2007         AllInactive := false;
  1926         if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  2008         if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1927         begin
  2009             begin
  1928             Gear^.State := Gear^.State or gsttmpFlag;
  2010             Gear^.State := Gear^.State or gsttmpFlag;
  1929             inc(Gear^.Damage, hwRound(Gear^.dY * _70));
  2011             inc(Gear^.Damage, hwRound(Gear^.dY * _70));
  1930             for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
  2012             for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
  1931             begin
  2013                 begin
  1932                 particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,
  2014                 particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,vgtDust);
  1933                             vgtDust);
  2015                 if particle <> nil then
  1934                 if particle <> nil then particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
  2016                     particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
       
  2017                 end
  1935             end
  2018             end
  1936         end
  2019         else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1937         else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1)
  2020                 inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  1938                  then
  2021                 
  1939                  inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  2022         else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1940         else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0)
  2023                 inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  1941                  then
  2024                 
  1942                  inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  2025         else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
  1943         else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1)
  2026                 inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
  1944                  then
       
  1945                  inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
       
  1946 
  2027 
  1947         doStepFallingGear(Gear);
  2028         doStepFallingGear(Gear);
  1948         CalcRotationDirAngle(Gear);
  2029         CalcRotationDirAngle(Gear);
  1949         //CheckGearDrowning(Gear)
  2030         //CheckGearDrowning(Gear)
  1950     end
  2031         end
  1951     else
  2032     else
  1952     begin
  2033         begin
  1953         Gear^.State := Gear^.State or gsttmpFlag;
  2034         Gear^.State := Gear^.State or gsttmpFlag;
  1954         AddGearCI(Gear)
  2035         AddGearCI(Gear)
  1955     end;
  2036         end;
  1956 
  2037 
  1957 (*
  2038 (*
  1958 Attempt to make a barrel knock itself over an edge.  Would need more checks to avoid issues like burn damage
  2039 Attempt to make a barrel knock itself over an edge.  Would need more checks to avoid issues like burn damage
  1959     begin
  2040     begin
  1960     x:= hwRound(Gear^.X);
  2041     x:= hwRound(Gear^.X);
  1968                 Gear^.dX:= _0_08;
  2049                 Gear^.dX:= _0_08;
  1969             end;
  2050             end;
  1970     if Gear^.dX.QWordValue = 0 then AddGearCI(Gear)
  2051     if Gear^.dX.QWordValue = 0 then AddGearCI(Gear)
  1971     end; *)
  2052     end; *)
  1972 
  2053 
  1973     if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then Gear
  2054     if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1974         ^.dY := _0;
  2055         Gear^.dY := _0;
  1975     if hwAbs(Gear^.dX) < _0_001 then Gear^.dX := _0;
  2056     if hwAbs(Gear^.dX) < _0_001 then
       
  2057         Gear^.dX := _0;
  1976 
  2058 
  1977     if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
  2059     if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
  1978         if (cBarrelHealth div Gear^.Health) > 2 then
  2060         if (cBarrelHealth div Gear^.Health) > 2 then
  1979             AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke)
  2061             AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke)
  1980     else
  2062     else
  1981         AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
  2063         AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
  1982     dec(Gear^.Health, Gear^.Damage);
  2064     dec(Gear^.Health, Gear^.Damage);
  1983     Gear^.Damage := 0;
  2065     Gear^.Damage := 0;
  1984     if Gear^.Health <= 0 then Gear^.doStep := @doStepCase;
  2066     if Gear^.Health <= 0 then
       
  2067         Gear^.doStep := @doStepCase;
  1985     // Hand off to doStepCase for the explosion
  2068     // Hand off to doStepCase for the explosion
  1986 
  2069 
  1987 end;
  2070 end;
  1988 
  2071 
  1989 procedure doStepCase(Gear: PGear);
  2072 procedure doStepCase(Gear: PGear);
  1996 begin
  2079 begin
  1997     k := Gear^.Kind;
  2080     k := Gear^.Kind;
  1998     exBoom := false;
  2081     exBoom := false;
  1999 
  2082 
  2000     if (Gear^.Message and gmDestroy) > 0 then
  2083     if (Gear^.Message and gmDestroy) > 0 then
  2001     begin
  2084         begin
  2002         DeleteGear(Gear);
  2085         DeleteGear(Gear);
  2003         FreeActionsList;
  2086         FreeActionsList;
  2004         SetAllToActive;
  2087         SetAllToActive;
  2005         // something (hh, mine, etc...) could be on top of the case
  2088         // something (hh, mine, etc...) could be on top of the case
  2006         with CurrentHedgehog^ do
  2089         with CurrentHedgehog^ do
  2007             if Gear <> nil then Gear^.Message := Gear^.Message and (not (gmLJump or gmHJump));
  2090             if Gear <> nil then
       
  2091                 Gear^.Message := Gear^.Message and (not (gmLJump or gmHJump));
  2008         exit
  2092         exit
  2009     end;
  2093         end;
  2010 
  2094 
  2011     if k = gtExplosives then
  2095     if k = gtExplosives then
  2012     begin
  2096         begin
  2013         //if V > _0_03 then Gear^.State:= Gear^.State or gstAnimation;
  2097         //if V > _0_03 then Gear^.State:= Gear^.State or gstAnimation;
  2014         if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02))
  2098         if (hwAbs(Gear^.dX) > _0_15) or ((hwAbs(Gear^.dY) > _0_15) and (hwAbs(Gear^.dX) > _0_02)) then
  2015             then Gear^.doStep := @doStepRollingBarrel;
  2099             Gear^.doStep := @doStepRollingBarrel;
  2016 
  2100 
  2017         if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
  2101         if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
  2018             if (cBarrelHealth div Gear^.Health) > 2 then
  2102             if (cBarrelHealth div Gear^.Health) > 2 then
  2019                 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke)
  2103                 AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmoke)
  2020         else
  2104         else
  2021             AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
  2105             AddVisualGear(hwRound(Gear^.X) - 16 + Random(32), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
  2022         dec(Gear^.Health, Gear^.Damage);
  2106         dec(Gear^.Health, Gear^.Damage);
  2023         Gear^.Damage := 0;
  2107         Gear^.Damage := 0;
  2024         if Gear^.Health <= 0 then
  2108         if Gear^.Health <= 0 then
  2025             exBoom := true;
  2109             exBoom := true;
  2026     end;
  2110         end;
  2027 
  2111 
  2028     if (Gear^.Damage > 0) or exBoom then
  2112     if (Gear^.Damage > 0) or exBoom then
  2029     begin
  2113         begin
  2030         x := hwRound(Gear^.X);
  2114         x := hwRound(Gear^.X);
  2031         y := hwRound(Gear^.Y);
  2115         y := hwRound(Gear^.Y);
  2032         hog:= Gear^.Hedgehog;
  2116         hog:= Gear^.Hedgehog;
  2033 
  2117 
  2034         DeleteGear(Gear);
  2118         DeleteGear(Gear);
  2035         // <-- delete gear!
  2119         // <-- delete gear!
  2036 
  2120 
  2037         if k = gtCase then
  2121         if k = gtCase then
  2038         begin
  2122             begin
  2039             doMakeExplosion(x, y, 25, hog, EXPLAutoSound);
  2123             doMakeExplosion(x, y, 25, hog, EXPLAutoSound);
  2040             for i:= 0 to 63 do
  2124             for i:= 0 to 63 do
  2041                 AddGear(x, y, gtFlame, 0, _0, _0, 0);
  2125                 AddGear(x, y, gtFlame, 0, _0, _0, 0);
  2042         end
  2126             end
  2043         else if k = gtExplosives then
  2127         else if k = gtExplosives then
  2044             begin
  2128                 begin
  2045                 doMakeExplosion(x, y, 75, hog, EXPLAutoSound);
  2129                 doMakeExplosion(x, y, 75, hog, EXPLAutoSound);
  2046                 for i:= 0 to 31 do
  2130                 for i:= 0 to 31 do
  2047                 begin
  2131                     begin
  2048                     dX := AngleCos(i * 64) * _0_5 * (getrandom + _1);
  2132                     dX := AngleCos(i * 64) * _0_5 * (getrandom + _1);
  2049                     dY := AngleSin(i * 64) * _0_5 * (getrandom + _1);
  2133                     dY := AngleSin(i * 64) * _0_5 * (getrandom + _1);
  2050                     AddGear(x, y, gtFlame, 0, dX, dY, 0);
  2134                     AddGear(x, y, gtFlame, 0, dX, dY, 0);
  2051                     AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0);
  2135                     AddGear(x, y, gtFlame, gstTmpFlag, -dX, -dY, 0);
  2052                 end
  2136                     end
  2053             end;
  2137                 end;
  2054         exit
  2138             exit
  2055     end;
  2139         end;
  2056 
  2140 
  2057     if (Gear^.dY.QWordValue <> 0) or (TestCollisionYwithGear(Gear, 1) = 0) then
  2141     if (Gear^.dY.QWordValue <> 0)
  2058     begin
  2142     or (TestCollisionYwithGear(Gear, 1) = 0) then
       
  2143         begin
  2059         AllInactive := false;
  2144         AllInactive := false;
  2060         Gear^.dY := Gear^.dY + cGravity;
  2145         Gear^.dY := Gear^.dY + cGravity;
  2061         Gear^.Y := Gear^.Y + Gear^.dY;
  2146         Gear^.Y := Gear^.Y + Gear^.dY;
  2062         if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then SetAllHHToActive;
  2147         if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then
  2063         if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then Gear^.dY := _0;
  2148             SetAllHHToActive;
       
  2149             
       
  2150         if (Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, -1) <> 0) then
       
  2151             Gear^.dY := _0;
       
  2152             
  2064         if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  2153         if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  2065         begin
  2154             begin
  2066             if (Gear^.dY > _0_2) and (k = gtExplosives) then
  2155             if (Gear^.dY > _0_2) and (k = gtExplosives) then
  2067                 inc(Gear^.Damage, hwRound(Gear^.dY * _70));
  2156                 inc(Gear^.Damage, hwRound(Gear^.dY * _70));
  2068 
  2157 
  2069             if Gear^.dY > _0_2 then
  2158             if Gear^.dY > _0_2 then
  2070                 for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
  2159                 for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
  2071                     AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust)
  2160                     AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
  2072             ;
  2161                     
  2073             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
  2162             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
  2074             if Gear^.dY > - _0_001 then Gear^.dY := _0
  2163             if Gear^.dY > - _0_001 then
       
  2164                 Gear^.dY := _0
  2075             else if Gear^.dY < - _0_03 then
  2165             else if Gear^.dY < - _0_03 then
  2076                      PlaySound(Gear^.ImpactSound);
  2166                 PlaySound(Gear^.ImpactSound);
  2077         end;
  2167             end;
  2078         //if Gear^.dY > - _0_001 then Gear^.dY:= _0
  2168         //if Gear^.dY > - _0_001 then Gear^.dY:= _0
  2079         CheckGearDrowning(Gear);
  2169         CheckGearDrowning(Gear);
  2080     end;
  2170         end;
  2081 
  2171 
  2082     if (Gear^.dY.QWordValue = 0) then AddGearCI(Gear)
  2172     if (Gear^.dY.QWordValue = 0) then
  2083     else if (Gear^.dY.QWordValue <> 0) then DeleteCI(Gear)
  2173         AddGearCI(Gear)
       
  2174     else if (Gear^.dY.QWordValue <> 0) then
       
  2175         DeleteCI(Gear)
  2084 end;
  2176 end;
  2085 
  2177 
  2086 ////////////////////////////////////////////////////////////////////////////////
  2178 ////////////////////////////////////////////////////////////////////////////////
  2087 
  2179 
  2088 procedure doStepTarget(Gear: PGear);
  2180 procedure doStepTarget(Gear: PGear);
  2093     if (Gear^.Tag = 0) and (Gear^.Timer < 1000) then
  2185     if (Gear^.Tag = 0) and (Gear^.Timer < 1000) then
  2094         inc(Gear^.Timer)
  2186         inc(Gear^.Timer)
  2095     else if Gear^.Tag = 1 then
  2187     else if Gear^.Tag = 1 then
  2096         Gear^.Tag := 2
  2188         Gear^.Tag := 2
  2097     else if Gear^.Tag = 2 then
  2189     else if Gear^.Tag = 2 then
  2098              if Gear^.Timer > 0 then
  2190             if Gear^.Timer > 0 then
  2099                  dec(Gear^.Timer)
  2191                 dec(Gear^.Timer)
  2100     else
  2192     else
  2101     begin
  2193         begin
  2102         DeleteGear(Gear);
  2194         DeleteGear(Gear);
  2103         exit;
  2195         exit;
  2104     end;
  2196         end;
  2105 
  2197 
  2106     doStepCase(Gear)
  2198     doStepCase(Gear)
  2107 end;
  2199 end;
  2108 
  2200 
  2109 ////////////////////////////////////////////////////////////////////////////////
  2201 ////////////////////////////////////////////////////////////////////////////////
  2110 procedure doStepIdle(Gear: PGear);
  2202 procedure doStepIdle(Gear: PGear);
  2111 begin
  2203 begin
  2112     AllInactive := false;
  2204     AllInactive := false;
  2113     dec(Gear^.Timer);
  2205     dec(Gear^.Timer);
  2114     if Gear^.Timer = 0 then
  2206     if Gear^.Timer = 0 then
  2115     begin
  2207         begin
  2116         DeleteGear(Gear);
  2208         DeleteGear(Gear);
  2117         AfterAttack
  2209         AfterAttack
  2118     end
  2210         end
  2119 end;
  2211 end;
  2120 
  2212 
  2121 ////////////////////////////////////////////////////////////////////////////////
  2213 ////////////////////////////////////////////////////////////////////////////////
  2122 procedure doStepShover(Gear: PGear);
  2214 procedure doStepShover(Gear: PGear);
  2123 var 
  2215 var 
  2166 begin
  2258 begin
  2167     sticky:= (Gear^.State and gsttmpFlag) <> 0;
  2259     sticky:= (Gear^.State and gsttmpFlag) <> 0;
  2168     if not sticky then AllInactive := false;
  2260     if not sticky then AllInactive := false;
  2169 
  2261 
  2170     if TestCollisionYwithGear(Gear, 1) = 0 then
  2262     if TestCollisionYwithGear(Gear, 1) = 0 then
  2171     begin
  2263         begin
  2172         AllInactive := false;
  2264         AllInactive := false;
  2173 
  2265 
  2174         if ((GameTicks mod 100) = 0) then
  2266         if ((GameTicks mod 100) = 0) then
  2175             begin
  2267             begin
  2176             vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire, gstTmpFlag);
  2268             vgt:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFire, gstTmpFlag);
  2183             end;
  2275             end;
  2184 
  2276 
  2185 
  2277 
  2186         if Gear^.dX.QWordValue > _0_01.QWordValue then
  2278         if Gear^.dX.QWordValue > _0_01.QWordValue then
  2187             Gear^.dX := Gear^.dX * _0_995;
  2279             Gear^.dX := Gear^.dX * _0_995;
       
  2280             
  2188         Gear^.dY := Gear^.dY + cGravity;
  2281         Gear^.dY := Gear^.dY + cGravity;
  2189         // if sticky then Gear^.dY := Gear^.dY + cGravity;
  2282         // if sticky then Gear^.dY := Gear^.dY + cGravity;
  2190         if Gear^.dY.QWordValue > _0_2.QWordValue then Gear^.dY := Gear^.dY * _0_995;
  2283         
       
  2284         if Gear^.dY.QWordValue > _0_2.QWordValue then
       
  2285             Gear^.dY := Gear^.dY * _0_995;
  2191 
  2286 
  2192         //if sticky then Gear^.X := Gear^.X + Gear^.dX else
  2287         //if sticky then Gear^.X := Gear^.X + Gear^.dX else
  2193         Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640;
  2288         Gear^.X := Gear^.X + Gear^.dX + cWindSpeed * 640;
  2194         Gear^.Y := Gear^.Y + Gear^.dY;
  2289         Gear^.Y := Gear^.Y + Gear^.dY;
  2195 
  2290 
  2196         if (hwRound(Gear^.Y) > cWaterLine) then
  2291         if (hwRound(Gear^.Y) > cWaterLine) then
  2197         begin
  2292             begin
  2198             gX := hwRound(Gear^.X);
  2293             gX := hwRound(Gear^.X);
  2199             for i:= 0 to 3 do
  2294             for i:= 0 to 3 do
  2200                 AddVisualGear(gX - 16 + Random(32), cWaterLine - 16 + Random(16), vgtSteam);
  2295                 AddVisualGear(gX - 16 + Random(32), cWaterLine - 16 + Random(16), vgtSteam);
  2201             PlaySound(sndVaporize);
  2296             PlaySound(sndVaporize);
  2202             DeleteGear(Gear);
  2297             DeleteGear(Gear);
  2203             exit
  2298             exit
       
  2299             end
  2204         end
  2300         end
  2205     end
       
  2206     else
  2301     else
  2207     begin
  2302         begin
  2208         if sticky then
  2303         if sticky then
  2209             begin
  2304             begin
  2210             Gear^.Radius := 7;
  2305             Gear^.Radius := 7;
  2211             tdX:= Gear^.dX;
  2306             tdX:= Gear^.dX;
  2212             tdY:= Gear^.dY;
  2307             tdY:= Gear^.dY;
  2223             begin
  2318             begin
  2224             dec(Gear^.Timer);
  2319             dec(Gear^.Timer);
  2225             inc(Gear^.Damage)
  2320             inc(Gear^.Damage)
  2226             end
  2321             end
  2227         else
  2322         else
  2228         begin
  2323             begin
  2229             gX := hwRound(Gear^.X);
  2324             gX := hwRound(Gear^.X);
  2230             gY := hwRound(Gear^.Y);
  2325             gY := hwRound(Gear^.Y);
  2231             // Standard fire
  2326             // Standard fire
  2232             if not sticky then
  2327             if not sticky then
  2233                 begin
  2328                 begin
  2243                     AmmoShove(Gear, 6, 100);
  2338                     AmmoShove(Gear, 6, 100);
  2244                     Gear^.dX:= tdX;
  2339                     Gear^.dX:= tdX;
  2245                     Gear^.dY:= tdY;
  2340                     Gear^.dY:= tdY;
  2246                     Gear^.Radius := 1;
  2341                     Gear^.Radius := 1;
  2247                     end
  2342                     end
  2248                 else if ((GameTicks and $3) = 3) then doMakeExplosion(gX, gY, 8, Gear^.Hedgehog, 0);//, EXPLNoDamage); 
  2343                 else if ((GameTicks and $3) = 3) then
       
  2344                     doMakeExplosion(gX, gY, 8, Gear^.Hedgehog, 0);//, EXPLNoDamage); 
  2249                 //DrawExplosion(gX, gY, 4);
  2345                 //DrawExplosion(gX, gY, 4);
       
  2346                 
  2250                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2347                 if ((GameTicks and $7) = 0) and (Random(2) = 0) then
  2251                     for i:= 1 to Random(2)+1 do
  2348                     for i:= 1 to Random(2)+1 do
  2252                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2349                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2253                 if Gear^.Health > 0 then dec(Gear^.Health);
  2350                         
       
  2351                 if Gear^.Health > 0 then
       
  2352                     dec(Gear^.Health);
  2254                 Gear^.Timer := 450 - Gear^.Tag * 8
  2353                 Gear^.Timer := 450 - Gear^.Tag * 8
  2255                 end
  2354                 end
  2256             else
  2355             else
  2257                 begin
  2356                 begin
  2258                 // Modified fire
  2357                 // Modified fire
  2264                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2363                         AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2265                     end;
  2364                     end;
  2266 
  2365 
  2267 // This one is interesting.  I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom.
  2366 // This one is interesting.  I think I understand the purpose, but I wonder if a bit more fuzzy of kicking could be done with getrandom.
  2268                 Gear^.Timer := 100 - Gear^.Tag * 3;
  2367                 Gear^.Timer := 100 - Gear^.Tag * 3;
  2269                 if (Gear^.Damage > 3000+Gear^.Tag*1500) then Gear^.Health := 0
  2368                 if (Gear^.Damage > 3000+Gear^.Tag*1500) then
       
  2369                     Gear^.Health := 0
       
  2370                 end
  2270             end
  2371             end
  2271         end
  2372         end;
  2272     end;
       
  2273     if Gear^.Health = 0 then
  2373     if Gear^.Health = 0 then
  2274     begin
  2374         begin
  2275         gX := hwRound(Gear^.X);
  2375         gX := hwRound(Gear^.X);
  2276         gY := hwRound(Gear^.Y);
  2376         gY := hwRound(Gear^.Y);
  2277         if not sticky then
  2377         if not sticky then
  2278         begin
  2378             begin
  2279             if ((GameTicks and $3) = 0) and (Random(1) = 0) then
  2379             if ((GameTicks and $3) = 0) and (Random(1) = 0) then
  2280             begin
  2380                 begin
  2281                 for i:= 1 to Random(2)+1 do
  2381                 for i:= 1 to Random(2)+1 do
  2282                 begin
  2382                     begin
  2283                     AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2383                     AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
       
  2384                     end;
  2284                 end;
  2385                 end;
  2285             end;
  2386             end
  2286         end
       
  2287         else
  2387         else
  2288         begin
  2388             begin
  2289             for i:= 0 to Random(3) do
  2389             for i:= 0 to Random(3) do
  2290             begin
  2390                 begin
  2291                 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2391                 AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2292             end;
  2392                 end;
  2293         end;
  2393             end;
  2294 
  2394 
  2295         DeleteGear(Gear)
  2395         DeleteGear(Gear)
  2296     end;
  2396         end;
  2297 end;
  2397 end;
  2298 
  2398 
  2299 ////////////////////////////////////////////////////////////////////////////////
  2399 ////////////////////////////////////////////////////////////////////////////////
  2300 procedure doStepFirePunchWork(Gear: PGear);
  2400 procedure doStepFirePunchWork(Gear: PGear);
  2301 var 
  2401 var 
  2302     HHGear: PGear;
  2402     HHGear: PGear;
  2303 begin
  2403 begin
  2304     AllInactive := false;
  2404     AllInactive := false;
  2305     if ((Gear^.Message and gmDestroy) <> 0) then
  2405     if ((Gear^.Message and gmDestroy) <> 0) then
  2306     begin
  2406         begin
  2307         DeleteGear(Gear);
  2407         DeleteGear(Gear);
  2308         AfterAttack;
  2408         AfterAttack;
  2309         exit
  2409         exit
  2310     end;
  2410         end;
  2311 
  2411 
  2312     HHGear := Gear^.Hedgehog^.Gear;
  2412     HHGear := Gear^.Hedgehog^.Gear;
  2313     if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then
  2413     if hwRound(HHGear^.Y) <= Gear^.Tag - 2 then
  2314     begin
  2414         begin
  2315         Gear^.Tag := hwRound(HHGear^.Y);
  2415         Gear^.Tag := hwRound(HHGear^.Y);
  2316         DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4, 2);
  2416         DrawTunnel(HHGear^.X - int2hwFloat(cHHRadius), HHGear^.Y - _1, _0_5, _0, cHHRadius * 4, 2);
  2317         HHGear^.State := HHGear^.State or gstNoDamage;
  2417         HHGear^.State := HHGear^.State or gstNoDamage;
  2318         Gear^.Y := HHGear^.Y;
  2418         Gear^.Y := HHGear^.Y;
  2319         AmmoShove(Gear, 30, 40);
  2419         AmmoShove(Gear, 30, 40);
  2320         HHGear^.State := HHGear^.State and (not gstNoDamage)
  2420         HHGear^.State := HHGear^.State and (not gstNoDamage)
  2321     end;
  2421         end;
  2322 
  2422 
  2323     HHGear^.dY := HHGear^.dY + cGravity;
  2423     HHGear^.dY := HHGear^.dY + cGravity;
  2324     if not (HHGear^.dY.isNegative) then
  2424     if not (HHGear^.dY.isNegative) then
  2325     begin
  2425         begin
  2326         HHGear^.State := HHGear^.State or gstMoving;
  2426         HHGear^.State := HHGear^.State or gstMoving;
  2327         DeleteGear(Gear);
  2427         DeleteGear(Gear);
  2328         AfterAttack;
  2428         AfterAttack;
  2329         exit
  2429         exit
  2330     end;
  2430         end;
  2331 
  2431 
  2332     if CheckLandValue(hwRound(HHGear^.X), hwRound(HHGear^.Y + HHGear^.dY + SignAs(_6,Gear^.dY)),
  2432     if CheckLandValue(hwRound(HHGear^.X), hwRound(HHGear^.Y + HHGear^.dY + SignAs(_6,Gear^.dY)),
  2333        lfIndestructible) then
  2433         lfIndestructible) then
  2334         HHGear^.Y := HHGear^.Y + HHGear^.dY
  2434             HHGear^.Y := HHGear^.Y + HHGear^.dY
  2335 end;
  2435 end;
  2336 
  2436 
  2337 procedure doStepFirePunch(Gear: PGear);
  2437 procedure doStepFirePunch(Gear: PGear);
  2338 var 
  2438 var 
  2339     HHGear: PGear;
  2439     HHGear: PGear;
  2364     HHGear := Gear^.Hedgehog^.Gear;
  2464     HHGear := Gear^.Hedgehog^.Gear;
  2365 
  2465 
  2366     inc(Gear^.Timer);
  2466     inc(Gear^.Timer);
  2367 
  2467 
  2368     if (TestCollisionYwithGear(HHGear, 1) <> 0)
  2468     if (TestCollisionYwithGear(HHGear, 1) <> 0)
  2369        or ((HHGear^.State and gstHHDriven) = 0)
  2469     or ((HHGear^.State and gstHHDriven) = 0)
  2370        or CheckGearDrowning(HHGear)
  2470     or CheckGearDrowning(HHGear)
  2371        or ((Gear^.Message and gmAttack) <> 0) then
  2471     or ((Gear^.Message and gmAttack) <> 0) then
  2372     begin
  2472         begin
  2373         with HHGear^ do
  2473         with HHGear^ do
  2374         begin
  2474             begin
  2375             Message := 0;
  2475             Message := 0;
  2376             SetLittle(dX);
  2476             SetLittle(dX);
  2377             dY := _0;
  2477             dY := _0;
  2378             State := State or gstMoving;
  2478             State := State or gstMoving;
  2379         end;
  2479             end;
  2380         DeleteGear(Gear);
  2480         DeleteGear(Gear);
  2381         isCursorVisible := false;
  2481         isCursorVisible := false;
  2382         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2482         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2383         exit
  2483         exit
  2384     end;
  2484         end;
  2385 
  2485 
  2386     HHGear^.X := HHGear^.X + cWindSpeed * 200;
  2486     HHGear^.X := HHGear^.X + cWindSpeed * 200;
  2387 
  2487 
  2388     if (Gear^.Message and gmLeft) <> 0 then HHGear^.X := HHGear^.X - cMaxWindSpeed * 80
  2488     if (Gear^.Message and gmLeft) <> 0 then
  2389     else if (Gear^.Message and gmRight) <> 0 then HHGear^.X := HHGear^.X + cMaxWindSpeed * 80;
  2489         HHGear^.X := HHGear^.X - cMaxWindSpeed * 80
  2390     if (Gear^.Message and gmUp) <> 0 then HHGear^.Y := HHGear^.Y - cGravity * 40
  2490         
  2391     else if (Gear^.Message and gmDown) <> 0 then HHGear^.Y := HHGear^.Y + cGravity * 40;
  2491     else if (Gear^.Message and gmRight) <> 0 then
       
  2492         HHGear^.X := HHGear^.X + cMaxWindSpeed * 80;
       
  2493         
       
  2494     if (Gear^.Message and gmUp) <> 0 then
       
  2495         HHGear^.Y := HHGear^.Y - cGravity * 40
       
  2496         
       
  2497     else if (Gear^.Message and gmDown) <> 0 then
       
  2498         HHGear^.Y := HHGear^.Y + cGravity * 40;
  2392 
  2499 
  2393     // don't drift into obstacles
  2500     // don't drift into obstacles
  2394     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
  2501     if TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
  2395         HHGear^.X := HHGear^.X - int2hwFloat(hwSign(HHGear^.dX));
  2502         HHGear^.X := HHGear^.X - int2hwFloat(hwSign(HHGear^.dX));
  2396     HHGear^.Y := HHGear^.Y + cGravity * 100;
  2503     HHGear^.Y := HHGear^.Y + cGravity * 100;
  2424     Gear^.X := Gear^.X + cAirPlaneSpeed * Gear^.Tag;
  2531     Gear^.X := Gear^.X + cAirPlaneSpeed * Gear^.Tag;
  2425 
  2532 
  2426     if (Gear^.Health > 0)and(not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  2533     if (Gear^.Health > 0)and(not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  2427         begin
  2534         begin
  2428         dec(Gear^.Health);
  2535         dec(Gear^.Health);
  2429         case Gear^.State of 
  2536             case Gear^.State of 
  2430             0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed *
  2537                 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  2431                              Gear^.Tag, _0, 0);
  2538                 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed * Gear^.Tag, _0, 0);
  2432             1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed *
  2539                 2: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtNapalmBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  2433                              Gear^.Tag, _0, 0);
  2540                 3: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtDrill, gsttmpFlag, cBombsSpeed * Gear^.Tag, _0, Gear^.Timer + 1);
  2434             2: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtNapalmBomb, 0, cBombsSpeed *
       
  2435                              Gear^.Tag, _0, 0);
       
  2436             3: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtDrill, gsttmpFlag, cBombsSpeed *
       
  2437                              Gear^.Tag, _0, Gear^.Timer + 1);
       
  2438             //4: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtWaterMelon, 0, cBombsSpeed *
  2541             //4: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtWaterMelon, 0, cBombsSpeed *
  2439             //                 Gear^.Tag, _0, 5000);
  2542             //                 Gear^.Tag, _0, 5000);
  2440             end;
  2543             end;
  2441         Gear^.dX := Gear^.dX + int2hwFloat(30 * Gear^.Tag);
  2544         Gear^.dX := Gear^.dX + int2hwFloat(30 * Gear^.Tag);
  2442         StopSound(Gear^.SoundChannel, 4000);
  2545         StopSound(Gear^.SoundChannel, 4000);
  2444 
  2547 
  2445     if (GameTicks and $3F) = 0 then
  2548     if (GameTicks and $3F) = 0 then
  2446         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  2549         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  2447 
  2550 
  2448     if (hwRound(Gear^.X) > (LAND_WIDTH+2048)) or (hwRound(Gear^.X) < -2048) then
  2551     if (hwRound(Gear^.X) > (LAND_WIDTH+2048)) or (hwRound(Gear^.X) < -2048) then
  2449     begin
  2552         begin
  2450         // avoid to play forever (is this necessary?)
  2553         // avoid to play forever (is this necessary?)
  2451         StopSound(Gear^.SoundChannel);
  2554         StopSound(Gear^.SoundChannel);
  2452         DeleteGear(Gear)
  2555         DeleteGear(Gear)
  2453     end;
  2556         end;
  2454 end;
  2557 end;
  2455 
  2558 
  2456 procedure doStepAirAttack(Gear: PGear);
  2559 procedure doStepAirAttack(Gear: PGear);
  2457 begin
  2560 begin
  2458     AllInactive := false;
  2561     AllInactive := false;
  2459 
  2562 
  2460     if Gear^.X.QWordValue = 0 then
  2563     if Gear^.X.QWordValue = 0 then
  2461     begin
  2564         begin
  2462         Gear^.Tag :=  1;
  2565         Gear^.Tag :=  1;
  2463         Gear^.X := -_2048;
  2566         Gear^.X := -_2048;
  2464     end
  2567         end
  2465     else
  2568     else
  2466     begin
  2569         begin
  2467         Gear^.Tag := -1;
  2570         Gear^.Tag := -1;
  2468         Gear^.X := int2hwFloat(LAND_WIDTH + 2048);
  2571         Gear^.X := int2hwFloat(LAND_WIDTH + 2048);
  2469     end;
  2572         end;
  2470 
  2573 
  2471     Gear^.Y := int2hwFloat(topY-300);
  2574     Gear^.Y := int2hwFloat(topY-300);
  2472     Gear^.dX := int2hwFloat(Gear^.Target.X - 5 * Gear^.Tag * 15);
  2575     Gear^.dX := int2hwFloat(Gear^.Target.X - 5 * Gear^.Tag * 15);
  2473 
  2576 
  2474     // calcs for Napalm Strike, so that it will hit the target (without wind at least :P)
  2577     // calcs for Napalm Strike, so that it will hit the target (without wind at least :P)
  2490 procedure doStepAirBomb(Gear: PGear);
  2593 procedure doStepAirBomb(Gear: PGear);
  2491 begin
  2594 begin
  2492     AllInactive := false;
  2595     AllInactive := false;
  2493     doStepFallingGear(Gear);
  2596     doStepFallingGear(Gear);
  2494     if (Gear^.State and gstCollision) <> 0 then
  2597     if (Gear^.State and gstCollision) <> 0 then
  2495     begin
  2598         begin
  2496         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  2599         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  2497         DeleteGear(Gear);
  2600         DeleteGear(Gear);
  2498         performRumble();
  2601         performRumble();
  2499         exit
  2602         exit
  2500     end;
  2603         end;
  2501     if (GameTicks and $3F) = 0 then
  2604     if (GameTicks and $3F) = 0 then
  2502         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
  2605         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
  2503 end;
  2606 end;
  2504 
  2607 
  2505 ////////////////////////////////////////////////////////////////////////////////
  2608 ////////////////////////////////////////////////////////////////////////////////
  2515     tx := int2hwFloat(Gear^.Target.X);
  2618     tx := int2hwFloat(Gear^.Target.X);
  2516     ty := int2hwFloat(Gear^.Target.Y);
  2619     ty := int2hwFloat(Gear^.Target.Y);
  2517     x := HHGear^.X;
  2620     x := HHGear^.X;
  2518     y := HHGear^.Y;
  2621     y := HHGear^.Y;
  2519 
  2622 
  2520     if (Distance(tx - x, ty - y) > _256) or
  2623     if (Distance(tx - x, ty - y) > _256)
  2521        (not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprAmGirder].Width div 2,
  2624     or (not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprAmGirder].Width div 2, Gear^.Target.Y - SpritesData[sprAmGirder].Height div 2, sprAmGirder, Gear^.State, true, false)) then
  2522        Gear^.Target.Y - SpritesData[sprAmGirder].Height div 2,
  2625         begin
  2523        sprAmGirder, Gear^.State, true, false)) then
       
  2524     begin
       
  2525         PlaySound(sndDenied);
  2626         PlaySound(sndDenied);
  2526         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2627         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2527         HHGear^.State := HHGear^.State and (not gstAttacking);
  2628         HHGear^.State := HHGear^.State and (not gstAttacking);
  2528         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2629         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2529         isCursorVisible := true;
  2630         isCursorVisible := true;
  2530         DeleteGear(Gear)
  2631         DeleteGear(Gear)
  2531     end
  2632         end
  2532     else 
  2633     else 
  2533     begin
  2634         begin
  2534         PlaySound(sndPlaced);
  2635         PlaySound(sndPlaced);
  2535         DeleteGear(Gear);
  2636         DeleteGear(Gear);
  2536         AfterAttack;
  2637         AfterAttack;
  2537     end;
  2638         end;
  2538 
  2639 
  2539     HHGear^.State := HHGear^.State and (not (gstAttacking or gstAttacked));
  2640     HHGear^.State := HHGear^.State and (not (gstAttacking or gstAttacked));
  2540     HHGear^.Message := HHGear^.Message and (not gmAttack);
  2641     HHGear^.Message := HHGear^.Message and (not gmAttack);
  2541 end;
  2642 end;
  2542 
  2643 
  2550     HHGear^.Y := HHGear^.Y + HHGear^.dY;
  2651     HHGear^.Y := HHGear^.Y + HHGear^.dY;
  2551     HHGear^.X := HHGear^.X + HHGear^.dX;
  2652     HHGear^.X := HHGear^.X + HHGear^.dX;
  2552     // hedgehog falling to collect cases
  2653     // hedgehog falling to collect cases
  2553     HHGear^.dY := HHGear^.dY + cGravity;
  2654     HHGear^.dY := HHGear^.dY + cGravity;
  2554     if (TestCollisionYwithGear(HHGear, 1) <> 0)
  2655     if (TestCollisionYwithGear(HHGear, 1) <> 0)
  2555        or CheckGearDrowning(HHGear) then
  2656     or CheckGearDrowning(HHGear) then
  2556     begin
  2657         begin
  2557         DeleteGear(Gear);
  2658         DeleteGear(Gear);
  2558         AfterAttack
  2659         AfterAttack
  2559     end
  2660         end
  2560 end;
  2661 end;
  2561 
  2662 
  2562 procedure doStepTeleportAnim(Gear: PGear);
  2663 procedure doStepTeleportAnim(Gear: PGear);
  2563 begin
  2664 begin
  2564     inc(Gear^.Timer);
  2665     inc(Gear^.Timer);
  2565     if Gear^.Timer = 65 then
  2666     if Gear^.Timer = 65 then
  2566     begin
  2667         begin
  2567         Gear^.Timer := 0;
  2668         Gear^.Timer := 0;
  2568         inc(Gear^.Pos);
  2669         inc(Gear^.Pos);
  2569         if Gear^.Pos = 11 then
  2670         if Gear^.Pos = 11 then
  2570             Gear^.doStep := @doStepTeleportAfter
  2671             Gear^.doStep := @doStepTeleportAfter
  2571     end;
  2672         end;
  2572 end;
  2673 end;
  2573 
  2674 
  2574 procedure doStepTeleport(Gear: PGear);
  2675 procedure doStepTeleport(Gear: PGear);
  2575 var 
  2676 var 
  2576     HHGear: PGear;
  2677     HHGear: PGear;
  2577 begin
  2678 begin
  2578     AllInactive := false;
  2679     AllInactive := false;
  2579 
  2680 
  2580     HHGear := Gear^.Hedgehog^.Gear;
  2681     HHGear := Gear^.Hedgehog^.Gear;
  2581     if not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2,
  2682     if not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2,
  2582        Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2,
  2683         Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2,
  2583        sprHHTelepMask, 0, false, false) then
  2684         sprHHTelepMask, 0, false, false) then
  2584     begin
  2685         begin
  2585         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2686         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2586         HHGear^.State := HHGear^.State and (not gstAttacking);
  2687         HHGear^.State := HHGear^.State and (not gstAttacking);
  2587         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2688         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2588         DeleteGear(Gear);
  2689         DeleteGear(Gear);
  2589         isCursorVisible := true;
  2690         isCursorVisible := true;
  2590         PlaySound(sndDenied)
  2691         PlaySound(sndDenied)
  2591     end
  2692         end
  2592     else
  2693     else
  2593     begin
  2694         begin
  2594         DeleteCI(HHGear);
  2695         DeleteCI(HHGear);
  2595         SetAllHHToActive;
  2696         SetAllHHToActive;
  2596         Gear^.doStep := @doStepTeleportAnim;
  2697         Gear^.doStep := @doStepTeleportAnim;
  2597 
  2698 
  2598   // copy old HH position and direction to Gear (because we need them for drawing the vanishing hog)
  2699   // copy old HH position and direction to Gear (because we need them for drawing the vanishing hog)
  2603         Gear^.Y := HHGear^.Y;
  2704         Gear^.Y := HHGear^.Y;
  2604         HHGear^.X := int2hwFloat(Gear^.Target.X);
  2705         HHGear^.X := int2hwFloat(Gear^.Target.X);
  2605         HHGear^.Y := int2hwFloat(Gear^.Target.Y);
  2706         HHGear^.Y := int2hwFloat(Gear^.Target.Y);
  2606         HHGear^.State := HHGear^.State or gstMoving;
  2707         HHGear^.State := HHGear^.State or gstMoving;
  2607         playSound(sndWarp)
  2708         playSound(sndWarp)
  2608     end;
  2709         end;
  2609     Gear^.Target.X:= NoPointX
  2710     Gear^.Target.X:= NoPointX
  2610 end;
  2711 end;
  2611 
  2712 
  2612 ////////////////////////////////////////////////////////////////////////////////
  2713 ////////////////////////////////////////////////////////////////////////////////
  2613 procedure doStepSwitcherWork(Gear: PGear);
  2714 procedure doStepSwitcherWork(Gear: PGear);
  2616     Msg, State: Longword;
  2717     Msg, State: Longword;
  2617 begin
  2718 begin
  2618     AllInactive := false;
  2719     AllInactive := false;
  2619 
  2720 
  2620     if ((Gear^.Message and (not gmSwitch)) <> 0) or (TurnTimeLeft = 0) then
  2721     if ((Gear^.Message and (not gmSwitch)) <> 0) or (TurnTimeLeft = 0) then
  2621     begin
  2722         begin
  2622         HHGear := Gear^.Hedgehog^.Gear;
  2723         HHGear := Gear^.Hedgehog^.Gear;
  2623         //Msg := Gear^.Message and (not gmSwitch);
  2724         //Msg := Gear^.Message and (not gmSwitch);
  2624         DeleteGear(Gear);
  2725         DeleteGear(Gear);
  2625         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2726         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2626 
  2727 
  2627         HHGear := CurrentHedgehog^.Gear;
  2728         HHGear := CurrentHedgehog^.Gear;
  2628         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2729         ApplyAmmoChanges(HHGear^.Hedgehog^);
  2629         //HHGear^.Message := Msg;
  2730         //HHGear^.Message := Msg;
  2630         exit
  2731         exit
  2631     end;
  2732         end;
  2632 
  2733 
  2633     if (Gear^.Message and gmSwitch) <> 0 then
  2734     if (Gear^.Message and gmSwitch) <> 0 then
  2634     begin
  2735         begin
  2635         HHGear := CurrentHedgehog^.Gear;
  2736         HHGear := CurrentHedgehog^.Gear;
  2636         HHGear^.Message := HHGear^.Message and (not gmSwitch);
  2737         HHGear^.Message := HHGear^.Message and (not gmSwitch);
  2637         Gear^.Message := Gear^.Message and (not gmSwitch);
  2738         Gear^.Message := Gear^.Message and (not gmSwitch);
  2638         State := HHGear^.State;
  2739         State := HHGear^.State;
  2639         HHGear^.State := 0;
  2740         HHGear^.State := 0;
  2643         InsertGearToList(HHGear);
  2744         InsertGearToList(HHGear);
  2644 
  2745 
  2645         PlaySound(sndSwitchHog);
  2746         PlaySound(sndSwitchHog);
  2646 
  2747 
  2647         repeat
  2748         repeat
  2648             CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.
  2749             CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber);
  2649                                          HedgehogsNumber);
       
  2650         until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0);
  2750         until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0);
  2651 
  2751 
  2652         CurrentHedgehog := @CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog];
  2752         CurrentHedgehog := @CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog];
  2653 
  2753 
  2654         HHGear := CurrentHedgehog^.Gear;
  2754         HHGear := CurrentHedgehog^.Gear;
  2658         HHGear^.Z := cCurrHHZ;
  2758         HHGear^.Z := cCurrHHZ;
  2659         RemoveGearFromList(HHGear);
  2759         RemoveGearFromList(HHGear);
  2660         InsertGearToList(HHGear);
  2760         InsertGearToList(HHGear);
  2661         Gear^.X := HHGear^.X;
  2761         Gear^.X := HHGear^.X;
  2662         Gear^.Y := HHGear^.Y
  2762         Gear^.Y := HHGear^.Y
  2663     end;
  2763         end;
  2664 end;
  2764 end;
  2665 
  2765 
  2666 procedure doStepSwitcher(Gear: PGear);
  2766 procedure doStepSwitcher(Gear: PGear);
  2667 var 
  2767 var 
  2668     HHGear: PGear;
  2768     HHGear: PGear;
  2670     Gear^.doStep := @doStepSwitcherWork;
  2770     Gear^.doStep := @doStepSwitcherWork;
  2671 
  2771 
  2672     HHGear := Gear^.Hedgehog^.Gear;
  2772     HHGear := Gear^.Hedgehog^.Gear;
  2673     OnUsedAmmo(HHGear^.Hedgehog^);
  2773     OnUsedAmmo(HHGear^.Hedgehog^);
  2674     with HHGear^ do
  2774     with HHGear^ do
  2675     begin
  2775         begin
  2676         State := State and (not gstAttacking);
  2776         State := State and (not gstAttacking);
  2677         Message := Message and (not gmAttack)
  2777         Message := Message and (not gmAttack)
  2678     end
  2778         end
  2679 end;
  2779 end;
  2680 
  2780 
  2681 ////////////////////////////////////////////////////////////////////////////////
  2781 ////////////////////////////////////////////////////////////////////////////////
  2682 procedure doStepMortar(Gear: PGear);
  2782 procedure doStepMortar(Gear: PGear);
  2683 var 
  2783 var 
  2689     dxn := Gear^.dX.isNegative;
  2789     dxn := Gear^.dX.isNegative;
  2690     dyn := Gear^.dY.isNegative;
  2790     dyn := Gear^.dY.isNegative;
  2691 
  2791 
  2692     doStepFallingGear(Gear);
  2792     doStepFallingGear(Gear);
  2693     if (Gear^.State and gstCollision) <> 0 then
  2793     if (Gear^.State and gstCollision) <> 0 then
  2694     begin
  2794         begin
  2695         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, Gear^.Hedgehog, EXPLAutoSound);
  2795         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 20, Gear^.Hedgehog, EXPLAutoSound);
  2696 
  2796 
  2697         Gear^.dX.isNegative := not dxn;
  2797         Gear^.dX.isNegative := not dxn;
  2698         Gear^.dY.isNegative := not dyn;
  2798         Gear^.dY.isNegative := not dyn;
  2699         for i:= 0 to 4 do
  2799         for i:= 0 to 4 do
  2700         begin
  2800             begin
  2701             dX := Gear^.dX + (GetRandom - _0_5) * _0_03;
  2801             dX := Gear^.dX + (GetRandom - _0_5) * _0_03;
  2702             dY := Gear^.dY + (GetRandom - _0_5) * _0_03;
  2802             dY := Gear^.dY + (GetRandom - _0_5) * _0_03;
  2703             AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, dX, dY, 25);
  2803             AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtCluster, 0, dX, dY, 25);
  2704         end;
  2804             end;
  2705 
  2805 
  2706         DeleteGear(Gear);
  2806         DeleteGear(Gear);
  2707         exit
  2807         exit
  2708     end;
  2808         end;
  2709 
  2809 
  2710     if (GameTicks and $3F) = 0 then
  2810     if (GameTicks and $3F) = 0 then
  2711         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
  2811         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
  2712 end;
  2812 end;
  2713 
  2813 
  2721     sparkles: PVisualGear;
  2821     sparkles: PVisualGear;
  2722     hasWishes: boolean;
  2822     hasWishes: boolean;
  2723 begin
  2823 begin
  2724     AllInactive := false;
  2824     AllInactive := false;
  2725     hasWishes:= ((Gear^.Message and (gmPrecise or gmSwitch)) = (gmPrecise or gmSwitch));
  2825     hasWishes:= ((Gear^.Message and (gmPrecise or gmSwitch)) = (gmPrecise or gmSwitch));
  2726     if hasWishes then Gear^.AdvBounce:= 1;
  2826     if hasWishes then
       
  2827         Gear^.AdvBounce:= 1;
  2727 
  2828 
  2728     HHGear := Gear^.Hedgehog^.Gear;
  2829     HHGear := Gear^.Hedgehog^.Gear;
  2729     HHGear^.State := HHGear^.State or gstNoDamage;
  2830     HHGear^.State := HHGear^.State or gstNoDamage;
  2730     DeleteCI(HHGear);
  2831     DeleteCI(HHGear);
  2731 
  2832 
  2753 
  2854 
  2754         //  if TestCollisionXwithGear(HHGear, hwSign(Gear^.dX))
  2855         //  if TestCollisionXwithGear(HHGear, hwSign(Gear^.dX))
  2755         //      or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY)) then inc(Gear^.Damage, 3);
  2856         //      or TestCollisionYwithGear(HHGear, hwSign(Gear^.dY)) then inc(Gear^.Damage, 3);
  2756 
  2857 
  2757         dec(i)
  2858         dec(i)
  2758     until (i = 0) or (Gear^.Damage > Gear^.Health);
  2859     until (i = 0)
       
  2860     or (Gear^.Damage > Gear^.Health);
  2759 
  2861 
  2760     inc(upd);
  2862     inc(upd);
  2761     if upd > 3 then
  2863     if upd > 3 then
  2762     begin
  2864         begin
  2763         if Gear^.Health < 1500 then
  2865         if Gear^.Health < 1500 then
  2764         begin
  2866             begin
  2765             if Gear^.AdvBounce <> 0 then
  2867             if Gear^.AdvBounce <> 0 then
  2766                 Gear^.Pos := 3
  2868                 Gear^.Pos := 3
  2767             else
  2869             else
  2768                 Gear^.Pos := 2;
  2870                 Gear^.Pos := 2;
  2769         end;
  2871             end;
  2770 
  2872 
  2771         AmmoShove(Gear, 30, 40);
  2873         AmmoShove(Gear, 30, 40);
  2772 
  2874 
  2773         DrawTunnel(HHGear^.X - HHGear^.dX * 10,
  2875         DrawTunnel(HHGear^.X - HHGear^.dX * 10,
  2774                    HHGear^.Y - _2 - HHGear^.dY * 10 + hwAbs(HHGear^.dY) * 2,
  2876                     HHGear^.Y - _2 - HHGear^.dY * 10 + hwAbs(HHGear^.dY) * 2,
  2775         HHGear^.dX,
  2877         HHGear^.dX,
  2776         HHGear^.dY,
  2878         HHGear^.dY,
  2777         20 + cHHRadius * 2,
  2879         20 + cHHRadius * 2,
  2778         cHHRadius * 2 + 7);
  2880         cHHRadius * 2 + 7);
  2779 
  2881 
  2780         upd := 0
  2882         upd := 0
  2781     end;
  2883         end;
  2782 
  2884 
  2783     if Gear^.Health < Gear^.Damage then
  2885     if Gear^.Health < Gear^.Damage then
  2784     begin
  2886         begin
  2785         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  2887         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  2786         if hasWishes then
  2888         if hasWishes then
  2787             for i:= 0 to 31 do
  2889             for i:= 0 to 31 do
  2788                 begin
  2890                 begin
  2789                 sparkles:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
  2891                 sparkles:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot);
  2792                         begin
  2894                         begin
  2793                         Tint:= ((random(210)+45) shl 24) or ((random(210)+45) shl 16) or ((random(210)+45) shl 8) or $FF;
  2895                         Tint:= ((random(210)+45) shl 24) or ((random(210)+45) shl 16) or ((random(210)+45) shl 8) or $FF;
  2794                         Angle:= random * 360;
  2896                         Angle:= random * 360;
  2795                         dx:= 0.001 * (random(200));
  2897                         dx:= 0.001 * (random(200));
  2796                         dy:= 0.001 * (random(200));
  2898                         dy:= 0.001 * (random(200));
  2797                         if random(2) = 0 then dx := -dx;
  2899                         if random(2) = 0 then
  2798                         if random(2) = 0 then dy := -dy;
  2900                             dx := -dx;
       
  2901                         if random(2) = 0 then
       
  2902                             dy := -dy;
  2799                         FrameTicks:= random(400) + 250
  2903                         FrameTicks:= random(400) + 250
  2800                         end
  2904                         end
  2801                 end;
  2905                 end;
  2802         AfterAttack;
  2906         AfterAttack;
  2803         DeleteGear(Gear);
  2907         DeleteGear(Gear);
  2804         DeleteGear(HHGear);
  2908         DeleteGear(HHGear);
  2805     end
  2909     end
  2806     else
  2910     else
  2807     begin
  2911         begin
  2808         dec(Gear^.Health, Gear^.Damage);
  2912         dec(Gear^.Health, Gear^.Damage);
  2809         Gear^.Damage := 0
  2913         Gear^.Damage := 0
  2810     end
  2914         end
  2811 end;
  2915 end;
  2812 
  2916 
  2813 procedure doStepKamikazeIdle(Gear: PGear);
  2917 procedure doStepKamikazeIdle(Gear: PGear);
  2814 begin
  2918 begin
  2815     AllInactive := false;
  2919     AllInactive := false;
  2854 procedure doStepCakeExpl(Gear: PGear);
  2958 procedure doStepCakeExpl(Gear: PGear);
  2855 begin
  2959 begin
  2856     AllInactive := false;
  2960     AllInactive := false;
  2857 
  2961 
  2858     inc(Gear^.Tag);
  2962     inc(Gear^.Tag);
  2859     if Gear^.Tag < 2250 then exit;
  2963     if Gear^.Tag < 2250 then
       
  2964         exit;
  2860 
  2965 
  2861     doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg, Gear^.Hedgehog, EXPLAutoSound);
  2966     doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), cakeDmg, Gear^.Hedgehog, EXPLAutoSound);
  2862     AfterAttack;
  2967     AfterAttack;
  2863     DeleteGear(Gear)
  2968     DeleteGear(Gear)
  2864 end;
  2969 end;
  2869     dmg: LongInt;
  2974     dmg: LongInt;
  2870 begin
  2975 begin
  2871     AllInactive := false;
  2976     AllInactive := false;
  2872 
  2977 
  2873     inc(Gear^.Tag);
  2978     inc(Gear^.Tag);
  2874     if Gear^.Tag < 100 then exit;
  2979     if Gear^.Tag < 100 then
       
  2980         exit;
  2875     Gear^.Tag := 0;
  2981     Gear^.Tag := 0;
  2876 
  2982 
  2877     if Gear^.Pos = 0 then
  2983     if Gear^.Pos = 0 then
  2878     begin
  2984         begin
  2879         gi := GearsList;
  2985         gi := GearsList;
  2880         while gi <> nil do
  2986         while gi <> nil do
  2881         begin
  2987             begin
  2882             dmg := cakeDmg * 2 - hwRound(Distance(gi^.X - Gear^.X, gi^.Y - Gear^.Y));
  2988             dmg := cakeDmg * 2 - hwRound(Distance(gi^.X - Gear^.X, gi^.Y - Gear^.Y));
  2883             if (dmg > 1) and (gi^.Kind = gtHedgehog) then
  2989             if (dmg > 1) and (gi^.Kind = gtHedgehog) then
  2884                 if (CurrentHedgehog^.Gear = gi) and (not gi^.Invulnerable) then
  2990                 if (CurrentHedgehog^.Gear = gi) and (not gi^.Invulnerable) then
  2885                     gi^.State := gi^.State or gstLoser
  2991                     gi^.State := gi^.State or gstLoser
  2886             else
  2992             else
  2887                 gi^.State := gi^.State or gstWinner;
  2993                 gi^.State := gi^.State or gstWinner;
  2888             gi := gi^.NextGear
  2994             gi := gi^.NextGear
  2889         end;
  2995             end;
  2890         Gear^.doStep := @doStepCakeExpl;
  2996         Gear^.doStep := @doStepCakeExpl;
  2891         PlaySound(sndCake)
  2997         PlaySound(sndCake)
  2892     end
  2998         end
  2893     else dec(Gear^.Pos)
  2999     else dec(Gear^.Pos)
  2894 end;
  3000 end;
  2895 
  3001 
  2896 
  3002 
  2897 procedure PrevAngle(Gear: PGear; dA: LongInt);
  3003 procedure PrevAngle(Gear: PGear; dA: LongInt);
  2913     tdx, tdy: hwFloat;
  3019     tdx, tdy: hwFloat;
  2914 begin
  3020 begin
  2915     AllInactive := false;
  3021     AllInactive := false;
  2916 
  3022 
  2917     inc(Gear^.Tag);
  3023     inc(Gear^.Tag);
  2918     if Gear^.Tag < 7 then exit;
  3024     if Gear^.Tag < 7 then
       
  3025         exit;
  2919 
  3026 
  2920     dA := hwSign(Gear^.dX);
  3027     dA := hwSign(Gear^.dX);
  2921     xx := dirs[Gear^.Angle].x;
  3028     xx := dirs[Gear^.Angle].x;
  2922     yy := dirs[Gear^.Angle].y;
  3029     yy := dirs[Gear^.Angle].y;
  2923     xxn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].x;
  3030     xxn := dirs[(LongInt(Gear^.Angle) + 4 + dA) mod 4].x;
  2925 
  3032 
  2926     if (xx = 0) then
  3033     if (xx = 0) then
  2927         if TestCollisionYwithGear(Gear, yy) <> 0 then
  3034         if TestCollisionYwithGear(Gear, yy) <> 0 then
  2928             PrevAngle(Gear, dA)
  3035             PrevAngle(Gear, dA)
  2929     else
  3036     else
  2930     begin
  3037         begin
  2931         Gear^.Tag := 0;
  3038         Gear^.Tag := 0;
  2932         Gear^.Y := Gear^.Y + int2hwFloat(yy);
  3039         Gear^.Y := Gear^.Y + int2hwFloat(yy);
  2933         if not TestCollisionXwithGear(Gear, xxn) then
  3040         if not TestCollisionXwithGear(Gear, xxn) then
  2934         begin
  3041             begin
  2935             Gear^.X := Gear^.X + int2hwFloat(xxn);
  3042             Gear^.X := Gear^.X + int2hwFloat(xxn);
  2936             NextAngle(Gear, dA)
  3043             NextAngle(Gear, dA)
  2937         end;
  3044             end;
  2938     end;
  3045         end;
  2939 
  3046 
  2940     if (yy = 0) then
  3047     if (yy = 0) then
  2941         if TestCollisionXwithGear(Gear, xx) then
  3048         if TestCollisionXwithGear(Gear, xx) then
  2942             PrevAngle(Gear, dA)
  3049             PrevAngle(Gear, dA)
  2943     else
  3050     else
  2944     begin
  3051         begin
  2945         Gear^.Tag := 0;
  3052         Gear^.Tag := 0;
  2946         Gear^.X := Gear^.X + int2hwFloat(xx);
  3053         Gear^.X := Gear^.X + int2hwFloat(xx);
  2947         if not TestCollisionY(Gear, yyn) then
  3054         if not TestCollisionY(Gear, yyn) then
  2948         begin
  3055             begin
  2949             Gear^.Y := Gear^.Y + int2hwFloat(yyn);
  3056             Gear^.Y := Gear^.Y + int2hwFloat(yyn);
  2950             NextAngle(Gear, dA)
  3057             NextAngle(Gear, dA)
  2951         end;
  3058             end;
  2952     end;
  3059         end;
  2953 
  3060 
  2954     if Gear^.Tag = 0 then
  3061     if Gear^.Tag = 0 then
  2955     begin
  3062         begin
  2956         CakeI := (CakeI + 1) mod cakeh;
  3063         CakeI := (CakeI + 1) mod cakeh;
  2957         tdx := CakePoints[CakeI].x - Gear^.X;
  3064         tdx := CakePoints[CakeI].x - Gear^.X;
  2958         tdy := - CakePoints[CakeI].y + Gear^.Y;
  3065         tdy := - CakePoints[CakeI].y + Gear^.Y;
  2959         CakePoints[CakeI].x := Gear^.X;
  3066         CakePoints[CakeI].x := Gear^.X;
  2960         CakePoints[CakeI].y := Gear^.Y;
  3067         CakePoints[CakeI].y := Gear^.Y;
  2961         Gear^.DirAngle := DxDy2Angle(tdx, tdy);
  3068         Gear^.DirAngle := DxDy2Angle(tdx, tdy);
  2962     end;
  3069         end;
  2963 
  3070 
  2964     dec(Gear^.Health);
  3071     dec(Gear^.Health);
  2965     Gear^.Timer := Gear^.Health*10;
  3072     Gear^.Timer := Gear^.Health*10;
  2966     if Gear^.Health mod 100 = 0 then Gear^.PortalCounter:= 0;
  3073     if Gear^.Health mod 100 = 0 then
       
  3074         Gear^.PortalCounter:= 0;
  2967     // This is not seconds, but at least it is *some* feedback
  3075     // This is not seconds, but at least it is *some* feedback
  2968     if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
  3076     if (Gear^.Health = 0) or ((Gear^.Message and gmAttack) <> 0) then
  2969     begin
  3077         begin
  2970         FollowGear := Gear;
  3078         FollowGear := Gear;
  2971         Gear^.RenderTimer := false;
  3079         Gear^.RenderTimer := false;
  2972         Gear^.doStep := @doStepCakeDown
  3080         Gear^.doStep := @doStepCakeDown
  2973     end
  3081         end
  2974 end;
  3082 end;
  2975 
  3083 
  2976 procedure doStepCakeUp(Gear: PGear);
  3084 procedure doStepCakeUp(Gear: PGear);
  2977 var 
  3085 var 
  2978     i: Longword;
  3086     i: Longword;
  2979 begin
  3087 begin
  2980     AllInactive := false;
  3088     AllInactive := false;
  2981 
  3089 
  2982     inc(Gear^.Tag);
  3090     inc(Gear^.Tag);
  2983     if Gear^.Tag < 100 then exit;
  3091     if Gear^.Tag < 100 then
       
  3092         exit;
  2984     Gear^.Tag := 0;
  3093     Gear^.Tag := 0;
  2985 
  3094 
  2986     if Gear^.Pos = 6 then
  3095     if Gear^.Pos = 6 then
  2987     begin
  3096         begin
  2988         for i:= 0 to Pred(cakeh) do
  3097         for i:= 0 to Pred(cakeh) do
  2989         begin
  3098             begin
  2990             CakePoints[i].x := Gear^.X;
  3099             CakePoints[i].x := Gear^.X;
  2991             CakePoints[i].y := Gear^.Y
  3100             CakePoints[i].y := Gear^.Y
  2992         end;
  3101             end;
  2993         CakeI := 0;
  3102         CakeI := 0;
  2994         Gear^.doStep := @doStepCakeWork
  3103         Gear^.doStep := @doStepCakeWork
  2995     end
  3104         end
  2996     else inc(Gear^.Pos)
  3105     else
       
  3106         inc(Gear^.Pos)
  2997 end;
  3107 end;
  2998 
  3108 
  2999 procedure doStepCakeFall(Gear: PGear);
  3109 procedure doStepCakeFall(Gear: PGear);
  3000 begin
  3110 begin
  3001     AllInactive := false;
  3111     AllInactive := false;
  3002 
  3112 
  3003     Gear^.dY := Gear^.dY + cGravity;
  3113     Gear^.dY := Gear^.dY + cGravity;
  3004     if TestCollisionYwithGear(Gear, 1) <> 0 then Gear^.doStep := @doStepCakeUp
  3114     if TestCollisionYwithGear(Gear, 1) <> 0 then
       
  3115         Gear^.doStep := @doStepCakeUp
  3005     else
  3116     else
  3006         begin
  3117         begin
  3007         Gear^.Y := Gear^.Y + Gear^.dY;
  3118         Gear^.Y := Gear^.Y + Gear^.dY;
  3008         if CheckGearDrowning(Gear) then AfterAttack
  3119         if CheckGearDrowning(Gear) then
       
  3120             AfterAttack
  3009         end
  3121         end
  3010 end;
  3122 end;
  3011 
  3123 
  3012 procedure doStepCake(Gear: PGear);
  3124 procedure doStepCake(Gear: PGear);
  3013 var 
  3125 var 
  3092         if heart <> nil then
  3204         if heart <> nil then
  3093             with heart^ do
  3205             with heart^ do
  3094                 begin
  3206                 begin
  3095                 dx:= 0.001 * (random(200));
  3207                 dx:= 0.001 * (random(200));
  3096                 dy:= 0.001 * (random(200));
  3208                 dy:= 0.001 * (random(200));
  3097                 if random(2) = 0 then dx := -dx;
  3209                 if random(2) = 0 then
  3098                 if random(2) = 0 then dy := -dy;
  3210                     dx := -dx;
       
  3211                 if random(2) = 0 then
       
  3212                     dy := -dy;
  3099                 FrameTicks:= random(750) + 1000;
  3213                 FrameTicks:= random(750) + 1000;
  3100                 State:= ord(sprSeduction)
  3214                 State:= ord(sprSeduction)
  3101                 end;
  3215                 end;
  3102         end;
  3216         end;
  3103 
  3217 
  3115 ////////////////////////////////////////////////////////////////////////////////
  3229 ////////////////////////////////////////////////////////////////////////////////
  3116 procedure doStepWaterUp(Gear: PGear);
  3230 procedure doStepWaterUp(Gear: PGear);
  3117 var 
  3231 var 
  3118     i: LongWord;
  3232     i: LongWord;
  3119 begin
  3233 begin
  3120     if (Gear^.Tag = 0) or (cWaterLine = 0) then
  3234     if (Gear^.Tag = 0)
  3121         begin
  3235     or (cWaterLine = 0) then
  3122             DeleteGear(Gear);
  3236         begin
  3123             exit
  3237         DeleteGear(Gear);
       
  3238         exit
  3124         end;
  3239         end;
  3125 
  3240 
  3126     AllInactive := false;
  3241     AllInactive := false;
  3127 
  3242 
  3128     inc(Gear^.Timer);
  3243     inc(Gear^.Timer);
  3130         Gear^.Timer := 0
  3245         Gear^.Timer := 0
  3131     else
  3246     else
  3132         exit;
  3247         exit;
  3133 
  3248 
  3134     if cWaterLine > 0 then
  3249     if cWaterLine > 0 then
  3135     begin
  3250         begin
  3136         dec(cWaterLine);
  3251         dec(cWaterLine);
  3137         for i:= 0 to LAND_WIDTH - 1 do
  3252         for i:= 0 to LAND_WIDTH - 1 do
  3138             Land[cWaterLine, i] := 0;
  3253             Land[cWaterLine, i] := 0;
  3139         SetAllToActive
  3254         SetAllToActive
  3140     end;
  3255         end;
  3141 
  3256 
  3142     dec(Gear^.Tag);
  3257     dec(Gear^.Tag);
  3143 end;
  3258 end;
  3144 
  3259 
  3145 ////////////////////////////////////////////////////////////////////////////////
  3260 ////////////////////////////////////////////////////////////////////////////////
  3161         Gear^.Y := Gear^.Y + Gear^.dY;
  3276         Gear^.Y := Gear^.Y + Gear^.dY;
  3162         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 2, 6);
  3277         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 2, 6);
  3163         if (Gear^.Timer mod 30) = 0 then
  3278         if (Gear^.Timer mod 30) = 0 then
  3164             AddVisualGear(hwRound(Gear^.X + _20 * Gear^.dX), hwRound(Gear^.Y + _20 * Gear^.dY), vgtDust);
  3279             AddVisualGear(hwRound(Gear^.X + _20 * Gear^.dX), hwRound(Gear^.Y + _20 * Gear^.dY), vgtDust);
  3165         if (CheckGearDrowning(Gear)) then
  3280         if (CheckGearDrowning(Gear)) then
  3166         begin
  3281            begin
  3167             StopSound(Gear^.SoundChannel);
  3282             StopSound(Gear^.SoundChannel);
  3168             exit
  3283             exit
  3169         end
  3284     end
  3170     end;
  3285     end;
  3171 
  3286 
  3172     if GameTicks > Gear^.FlightTime then t := CheckGearsCollision(Gear)
  3287     if GameTicks > Gear^.FlightTime then
       
  3288         t := CheckGearsCollision(Gear)
       
  3289         
  3173     else t := nil;
  3290     else t := nil;
  3174     //fixes drill not exploding when touching HH bug
  3291     //fixes drill not exploding when touching HH bug
  3175     if (Gear^.Timer = 0) or ((t <> nil) and (t^.Count <> 0)) or 
  3292     
  3176        ( ((Gear^.State and gsttmpFlag) = 0) and
  3293     if (Gear^.Timer = 0) or ((t <> nil) and (t^.Count <> 0))
  3177          (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0)
  3294     or ( ((Gear^.State and gsttmpFlag) = 0) and (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))))
  3178          and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))))
       
  3179 // CheckLandValue returns true if the type isn't matched
  3295 // CheckLandValue returns true if the type isn't matched
  3180        or (not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible)) then
  3296     or (not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible)) then
  3181         begin
  3297         begin
  3182         //out of time or exited ground
  3298         //out of time or exited ground
  3183         StopSound(Gear^.SoundChannel);
  3299         StopSound(Gear^.SoundChannel);
  3184         if (Gear^.State and gsttmpFlag) <> 0 then
  3300         if (Gear^.State and gsttmpFlag) <> 0 then
  3185             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound)
  3301             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound)
  3186         else
  3302         else
  3187             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  3303             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  3188         DeleteGear(Gear);
  3304         DeleteGear(Gear);
  3189         exit
  3305         exit
  3190         end
  3306         end
       
  3307         
  3191     else if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))) then
  3308     else if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))) then
  3192         begin
  3309         begin
  3193         StopSound(Gear^.SoundChannel);
  3310         StopSound(Gear^.SoundChannel);
  3194         Gear^.Tag := 1;
  3311         Gear^.Tag := 1;
  3195         Gear^.doStep := @doStepDrill
  3312         Gear^.doStep := @doStepDrill
  3216 
  3333 
  3217     if (GameTicks and $3F) = 0 then
  3334     if (GameTicks and $3F) = 0 then
  3218         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  3335         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  3219 
  3336 
  3220     if ((Gear^.State and gstCollision) <> 0) then
  3337     if ((Gear^.State and gstCollision) <> 0) then
  3221     begin
  3338         begin
  3222         //hit
  3339         //hit
  3223         Gear^.dX := oldDx;
  3340         Gear^.dX := oldDx;
  3224         Gear^.dY := oldDy;
  3341         Gear^.dY := oldDy;
  3225 
  3342 
  3226         if GameTicks > Gear^.FlightTime then t := CheckGearsCollision(Gear)
  3343         if GameTicks > Gear^.FlightTime then 
  3227         else t := nil;
  3344             t := CheckGearsCollision(Gear)
       
  3345         else
       
  3346             t := nil;
  3228         if (t = nil) or (t^.Count = 0) then
  3347         if (t = nil) or (t^.Count = 0) then
  3229             begin
  3348             begin
  3230             //hit the ground not the HH
  3349             //hit the ground not the HH
  3231             t2 := _0_5 / Distance(Gear^.dX, Gear^.dY);
  3350             t2 := _0_5 / Distance(Gear^.dX, Gear^.dY);
  3232             Gear^.dX := Gear^.dX * t2;
  3351             Gear^.dX := Gear^.dX * t2;
  3233             Gear^.dY := Gear^.dY * t2;
  3352             Gear^.dY := Gear^.dY * t2;
  3234             end
  3353             end
       
  3354             
  3235         else if (t <> nil) then
  3355         else if (t <> nil) then
  3236             begin
  3356             begin
  3237             //explode right on contact with HH
  3357             //explode right on contact with HH
  3238             if (Gear^.State and gsttmpFlag) <> 0 then
  3358             if (Gear^.State and gsttmpFlag) <> 0 then
  3239                 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound)
  3359                 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound)
  3243             exit;
  3363             exit;
  3244             end;
  3364             end;
  3245 
  3365 
  3246         Gear^.SoundChannel := LoopSound(sndDrillRocket);
  3366         Gear^.SoundChannel := LoopSound(sndDrillRocket);
  3247         Gear^.doStep := @doStepDrillDrilling;
  3367         Gear^.doStep := @doStepDrillDrilling;
       
  3368         
  3248         if (Gear^.State and gsttmpFlag) <> 0 then
  3369         if (Gear^.State and gsttmpFlag) <> 0 then
  3249             gear^.RenderTimer:= true;
  3370             gear^.RenderTimer:= true;
  3250         dec(Gear^.Timer)
  3371         dec(Gear^.Timer)
  3251     end
  3372         end
  3252     else if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Tag <> 0) then
  3373         
  3253          begin
  3374         else if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Tag <> 0) then
       
  3375             begin
  3254             if Gear^.Timer = 0 then
  3376             if Gear^.Timer = 0 then
  3255             begin
  3377                 begin
  3256                 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  3378                 doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  3257                 DeleteGear(Gear);
  3379                 DeleteGear(Gear);
  3258             end
  3380                 end
  3259             else
  3381             else
  3260                 dec(Gear^.Timer);
  3382                 dec(Gear^.Timer);
  3261          end;
  3383             end;
  3262 end;
  3384 end;
  3263 
  3385 
  3264 ////////////////////////////////////////////////////////////////////////////////
  3386 ////////////////////////////////////////////////////////////////////////////////
  3265 procedure doStepBallgunWork(Gear: PGear);
  3387 procedure doStepBallgunWork(Gear: PGear);
  3266 var 
  3388 var 
  3273     HHGear := Gear^.Hedgehog^.Gear;
  3395     HHGear := Gear^.Hedgehog^.Gear;
  3274     HedgehogChAngle(HHGear);
  3396     HedgehogChAngle(HHGear);
  3275     gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle);
  3397     gX := hwRound(Gear^.X) + GetLaunchX(amBallgun, hwSign(HHGear^.dX), HHGear^.Angle);
  3276     gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle);
  3398     gY := hwRound(Gear^.Y) + GetLaunchY(amBallgun, HHGear^.Angle);
  3277     if (Gear^.Timer mod 100) = 0 then
  3399     if (Gear^.Timer mod 100) = 0 then
  3278     begin
  3400         begin
  3279         rx := rndSign(getRandom * _0_1);
  3401         rx := rndSign(getRandom * _0_1);
  3280         ry := rndSign(getRandom * _0_1);
  3402         ry := rndSign(getRandom * _0_1);
  3281 
  3403 
  3282         AddGear(gx, gy, gtBall, 0,
  3404         AddGear(gx, gy, gtBall, 0, SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx, AngleCos(HHGear^.Angle) * ( - _0_8) + ry, 0);
  3283                 SignAs(AngleSin(HHGear^.Angle) * _0_8, HHGear^.dX) + rx,
       
  3284         AngleCos(HHGear^.Angle) * ( - _0_8) + ry,
       
  3285         0);
       
  3286 
  3405 
  3287         PlaySound(sndGun);
  3406         PlaySound(sndGun);
  3288     end;
  3407         end;
  3289 
  3408 
  3290     if (Gear^.Timer = 0) or (HHGear^.Damage <> 0) then
  3409     if (Gear^.Timer = 0) or (HHGear^.Damage <> 0) then
  3291     begin
  3410         begin
  3292         DeleteGear(Gear);
  3411         DeleteGear(Gear);
  3293         AfterAttack
  3412         AfterAttack
  3294     end
  3413         end
  3295 end;
  3414 end;
  3296 
  3415 
  3297 procedure doStepBallgun(Gear: PGear);
  3416 procedure doStepBallgun(Gear: PGear);
  3298 var 
  3417 var 
  3299     HHGear: PGear;
  3418     HHGear: PGear;
  3319     AllInactive := false;
  3438     AllInactive := false;
  3320 
  3439 
  3321     HHGear := Gear^.Hedgehog^.Gear;
  3440     HHGear := Gear^.Hedgehog^.Gear;
  3322     FollowGear := Gear;
  3441     FollowGear := Gear;
  3323 
  3442 
  3324     if Gear^.Timer > 0 then dec(Gear^.Timer);
  3443     if Gear^.Timer > 0 then
       
  3444         dec(Gear^.Timer);
  3325 
  3445 
  3326     fChanged := false;
  3446     fChanged := false;
  3327     if ((HHGear^.State and gstHHDriven) = 0) or (Gear^.Timer = 0) then
  3447     if ((HHGear^.State and gstHHDriven) = 0) or (Gear^.Timer = 0) then
  3328     begin
  3448         begin
  3329         fChanged := true;
  3449         fChanged := true;
  3330         if Gear^.Angle > 2048 then dec(Gear^.Angle)
  3450         if Gear^.Angle > 2048 then
       
  3451             dec(Gear^.Angle)
  3331         else
  3452         else
  3332             if Gear^.Angle < 2048 then inc(Gear^.Angle)
  3453             if Gear^.Angle < 2048 then
  3333         else fChanged := false
  3454                 inc(Gear^.Angle)
       
  3455         else
       
  3456             fChanged := false
  3334     end
  3457     end
  3335     else
  3458     else
  3336     begin
  3459         begin
  3337         if ((Gear^.Message and gmLeft) <> 0) then
  3460         if ((Gear^.Message and gmLeft) <> 0) then
  3338         begin
  3461             begin
  3339             fChanged := true;
  3462             fChanged := true;
  3340             Gear^.Angle := (Gear^.Angle + (4096 - cAngleSpeed)) mod 4096
  3463             Gear^.Angle := (Gear^.Angle + (4096 - cAngleSpeed)) mod 4096
  3341         end;
  3464             end;
  3342 
  3465 
  3343         if ((Gear^.Message and gmRight) <> 0) then
  3466         if ((Gear^.Message and gmRight) <> 0) then
  3344         begin
  3467             begin
  3345             fChanged := true;
  3468             fChanged := true;
  3346             Gear^.Angle := (Gear^.Angle + cAngleSpeed) mod 4096
  3469             Gear^.Angle := (Gear^.Angle + cAngleSpeed) mod 4096
  3347         end
  3470             end
  3348     end;
  3471         end;
  3349 
  3472 
  3350     if fChanged then
  3473     if fChanged then
  3351     begin
  3474         begin
  3352         Gear^.dX.isNegative := (Gear^.Angle > 2048);
  3475         Gear^.dX.isNegative := (Gear^.Angle > 2048);
  3353         if Gear^.dX.isNegative then
  3476         if Gear^.dX.isNegative then
  3354             trueAngle := 4096 - Gear^.Angle
  3477             trueAngle := 4096 - Gear^.Angle
  3355         else
  3478         else
  3356             trueAngle := Gear^.Angle;
  3479             trueAngle := Gear^.Angle;
  3357 
  3480 
  3358         Gear^.dX := SignAs(AngleSin(trueAngle), Gear^.dX) * _0_25;
  3481         Gear^.dX := SignAs(AngleSin(trueAngle), Gear^.dX) * _0_25;
  3359         Gear^.dY := AngleCos(trueAngle) * -_0_25;
  3482         Gear^.dY := AngleCos(trueAngle) * -_0_25;
  3360     end;
  3483         end;
  3361 
  3484 
  3362     Gear^.X := Gear^.X + Gear^.dX;
  3485     Gear^.X := Gear^.X + Gear^.dX;
  3363     Gear^.Y := Gear^.Y + Gear^.dY;
  3486     Gear^.Y := Gear^.Y + Gear^.dY;
  3364 
  3487 
  3365     if (GameTicks and $FF) = 0 then
  3488     if (GameTicks and $FF) = 0 then
  3367             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace)
  3490             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEvilTrace)
  3368     else
  3491     else
  3369         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  3492         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  3370 
  3493 
  3371     if ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then
  3494     if ((HHGear^.Message and gmAttack) <> 0) and (Gear^.Health <> 0) then
  3372     begin
  3495         begin
  3373         HHGear^.Message := HHGear^.Message and (not gmAttack);
  3496         HHGear^.Message := HHGear^.Message and (not gmAttack);
  3374         AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY *
  3497         AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, Gear^.dX * _0_5, Gear^.dY *
  3375         _0_5, 0);
  3498         _0_5, 0);
  3376         dec(Gear^.Health)
  3499         dec(Gear^.Health)
  3377     end;
  3500         end;
  3378 
  3501 
  3379     if ((HHGear^.Message and gmLJump) <> 0)
  3502     if ((HHGear^.Message and gmLJump) <> 0) and ((Gear^.State and gsttmpFlag) = 0) then
  3380        and ((Gear^.State and gsttmpFlag) = 0) then
  3503         begin
  3381     begin
       
  3382         Gear^.State := Gear^.State or gsttmpFlag;
  3504         Gear^.State := Gear^.State or gsttmpFlag;
  3383         PauseMusic;
  3505         PauseMusic;
  3384         playSound(sndRideOfTheValkyries);
  3506         playSound(sndRideOfTheValkyries);
  3385     end;
  3507         end;
  3386 
  3508 
  3387     // pickup bonuses
  3509     // pickup bonuses
  3388     t := CheckGearNear(Gear, gtCase, 36, 36);
  3510     t := CheckGearNear(Gear, gtCase, 36, 36);
  3389     if t <> nil then
  3511     if t <> nil then
  3390         PickUp(HHGear, t);
  3512         PickUp(HHGear, t);
  3391 
  3513 
  3392     CheckCollision(Gear);
  3514     CheckCollision(Gear);
  3393 
  3515 
  3394     if ((Gear^.State and gstCollision) <> 0) or CheckGearDrowning(Gear) then
  3516     if ((Gear^.State and gstCollision) <> 0) or CheckGearDrowning(Gear) then
  3395     begin
  3517         begin
  3396         StopSound(Gear^.SoundChannel);
  3518         StopSound(Gear^.SoundChannel);
  3397         StopSound(sndRideOfTheValkyries);
  3519         StopSound(sndRideOfTheValkyries);
  3398         ResumeMusic;
  3520         ResumeMusic;
  3399 
  3521 
  3400         if ((Gear^.State and gstCollision) <> 0) then
  3522         if ((Gear^.State and gstCollision) <> 0) then
  3401         begin
  3523             begin
  3402             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, Gear^.Hedgehog, EXPLAutoSound);
  3524             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, Gear^.Hedgehog, EXPLAutoSound);
  3403             for i:= 0 to 15 do
  3525             for i:= 0 to 15 do
  3404             begin
  3526                 begin
  3405                 dX := AngleCos(i * 64) * _0_5 * (GetRandom + _1);
  3527                 dX := AngleCos(i * 64) * _0_5 * (GetRandom + _1);
  3406                 dY := AngleSin(i * 64) * _0_5 * (GetRandom + _1);
  3528                 dY := AngleSin(i * 64) * _0_5 * (GetRandom + _1);
  3407                 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, dY, 0);
  3529                 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, dY, 0);
  3408                 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, -dY, 0);
  3530                 AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtFlame, 0, dX, -dY, 0);
  3409             end;
  3531                 end;
  3410             DeleteGear(Gear)
  3532             DeleteGear(Gear)
  3411         end;
  3533             end;
  3412 
  3534 
  3413         AfterAttack;
  3535         AfterAttack;
  3414         CurAmmoGear := nil;
  3536         CurAmmoGear := nil;
  3415         if (GameFlags and gfInfAttack) = 0 then
  3537         if (GameFlags and gfInfAttack) = 0 then
  3416             begin
  3538             begin
  3417             if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft;
  3539             if TagTurnTimeLeft = 0 then
       
  3540                 TagTurnTimeLeft:= TurnTimeLeft;
       
  3541                 
  3418             TurnTimeLeft:= 14 * 125;
  3542             TurnTimeLeft:= 14 * 125;
  3419             end;
  3543             end;
  3420 
  3544 
  3421         HHGear^.Message := 0;
  3545         HHGear^.Message := 0;
  3422         ParseCommand('/taunt ' + #1, true)
  3546         ParseCommand('/taunt ' + #1, true)
  3423     end
  3547         end
  3424 end;
  3548 end;
  3425 
  3549 
  3426 procedure doStepRCPlane(Gear: PGear);
  3550 procedure doStepRCPlane(Gear: PGear);
  3427 var 
  3551 var 
  3428     HHGear: PGear;
  3552     HHGear: PGear;
  3430     HHGear := Gear^.Hedgehog^.Gear;
  3554     HHGear := Gear^.Hedgehog^.Gear;
  3431     HHGear^.Message := 0;
  3555     HHGear^.Message := 0;
  3432     HHGear^.State := HHGear^.State or gstNotKickable;
  3556     HHGear^.State := HHGear^.State or gstNotKickable;
  3433     Gear^.Angle := HHGear^.Angle;
  3557     Gear^.Angle := HHGear^.Angle;
  3434     Gear^.Tag := hwSign(HHGear^.dX);
  3558     Gear^.Tag := hwSign(HHGear^.dX);
  3435     if HHGear^.dX.isNegative then Gear^.Angle := 4096 - Gear^.Angle;
  3559     
       
  3560     if HHGear^.dX.isNegative then
       
  3561         Gear^.Angle := 4096 - Gear^.Angle;
  3436     Gear^.doStep := @doStepRCPlaneWork
  3562     Gear^.doStep := @doStepRCPlaneWork
  3437 end;
  3563 end;
  3438 
  3564 
  3439 ////////////////////////////////////////////////////////////////////////////////
  3565 ////////////////////////////////////////////////////////////////////////////////
  3440 procedure doStepJetpackWork(Gear: PGear);
  3566 procedure doStepJetpackWork(Gear: PGear);
  3444     move: hwFloat;
  3570     move: hwFloat;
  3445     isUnderwater: Boolean;
  3571     isUnderwater: Boolean;
  3446     bubble: PVisualGear;
  3572     bubble: PVisualGear;
  3447 begin
  3573 begin
  3448     isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
  3574     isUnderwater:= cWaterLine < hwRound(Gear^.Y) + Gear^.Radius;
  3449     if Gear^.Pos > 0 then dec(Gear^.Pos);
  3575     if Gear^.Pos > 0 then
       
  3576         dec(Gear^.Pos);
  3450     AllInactive := false;
  3577     AllInactive := false;
  3451     HHGear := Gear^.Hedgehog^.Gear;
  3578     HHGear := Gear^.Hedgehog^.Gear;
  3452     //dec(Gear^.Timer);
  3579     //dec(Gear^.Timer);
  3453     move := _0_2;
  3580     move := _0_2;
  3454     fuel := 50;
  3581     fuel := 50;
  3468                     begin
  3595                     begin
  3469                     HHGear^.dY := HHGear^.dY - (move * _0_7);
  3596                     HHGear^.dY := HHGear^.dY - (move * _0_7);
  3470                     for i:= random(10)+10 downto 0 do
  3597                     for i:= random(10)+10 downto 0 do
  3471                         begin
  3598                         begin
  3472                         bubble := AddVisualGear(hwRound(HHGear^.X) - 8 + random(16), hwRound(HHGear^.Y) + 16 + random(8), vgtBubble);
  3599                         bubble := AddVisualGear(hwRound(HHGear^.X) - 8 + random(16), hwRound(HHGear^.Y) + 16 + random(8), vgtBubble);
  3473                         if bubble <> nil then bubble^.dY:= random(20)/10+0.1;
  3600                         if bubble <> nil then
       
  3601                             bubble^.dY:= random(20)/10+0.1;
  3474                         end
  3602                         end
  3475                     end
  3603                     end
  3476                 else HHGear^.dY := HHGear^.dY - move;
  3604                 else HHGear^.dY := HHGear^.dY - move;
  3477                 end;
  3605                 end;
  3478             dec(Gear^.Health, fuel);
  3606             dec(Gear^.Health, fuel);
  3511         begin
  3639         begin
  3512         Gear^.Timer := 0;
  3640         Gear^.Timer := 0;
  3513         Gear^.MsgParam := 0
  3641         Gear^.MsgParam := 0
  3514         end;
  3642         end;
  3515 
  3643 
  3516     if Gear^.Health < 0 then Gear^.Health := 0;
  3644     if Gear^.Health < 0 then
       
  3645         Gear^.Health := 0;
       
  3646         
  3517     i:= Gear^.Health div 20;
  3647     i:= Gear^.Health div 20;
       
  3648     
  3518     if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then
  3649     if (i <> Gear^.Damage) and ((GameTicks and $3F) = 0) then
  3519         begin
  3650         begin
  3520         Gear^.Damage:= i;
  3651         Gear^.Damage:= i;
  3521         //AddCaption('Fuel: '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate);
  3652         //AddCaption('Fuel: '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate);
  3522         FreeTexture(Gear^.Tex);
  3653         FreeTexture(Gear^.Tex);
  3523         Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) +
  3654         Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(i) + '%', cWhiteColor, fntSmall)
  3524                      '%', cWhiteColor, fntSmall)
       
  3525         end;
  3655         end;
  3526 
  3656 
  3527     if HHGear^.Message and (gmAttack or gmUp or gmPrecise or gmLeft or gmRight) <> 0 then 
  3657     if HHGear^.Message and (gmAttack or gmUp or gmPrecise or gmLeft or gmRight) <> 0 then 
  3528         Gear^.State := Gear^.State and (not gsttmpFlag);
  3658         Gear^.State := Gear^.State and (not gsttmpFlag);
       
  3659         
  3529     HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
  3660     HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
  3530     HHGear^.State := HHGear^.State or gstMoving;
  3661     HHGear^.State := HHGear^.State or gstMoving;
  3531 
  3662 
  3532     Gear^.X := HHGear^.X;
  3663     Gear^.X := HHGear^.X;
  3533     Gear^.Y := HHGear^.Y;
  3664     Gear^.Y := HHGear^.Y;
  3534     // For some reason I need to reapply followgear here, something else grabs it otherwise.
  3665     // For some reason I need to reapply followgear here, something else grabs it otherwise.
  3535     // This is probably not needed anymore
  3666     // This is probably not needed anymore
  3536     if not CurrentTeam^.ExtDriven then FollowGear := HHGear;
  3667     if not CurrentTeam^.ExtDriven then
  3537 
  3668         FollowGear := HHGear;
  3538     if not isUnderWater and hasBorder and ((HHGear^.X < _0) or (hwRound(HHGear^.X) > LAND_WIDTH)) then HHGear^.dY.isNegative:= false;
  3669 
  3539     if ((Gear^.State and gsttmpFlag) = 0) or (HHGear^.dY < _0) then doStepHedgehogMoving(HHGear);
  3670     if not isUnderWater and hasBorder and ((HHGear^.X < _0)
       
  3671     or (hwRound(HHGear^.X) > LAND_WIDTH)) then
       
  3672         HHGear^.dY.isNegative:= false;
       
  3673         
       
  3674     if ((Gear^.State and gsttmpFlag) = 0)
       
  3675     or (HHGear^.dY < _0) then
       
  3676         doStepHedgehogMoving(HHGear);
  3540 
  3677 
  3541     if // (Gear^.Health = 0)
  3678     if // (Gear^.Health = 0)
  3542         (HHGear^.Damage <> 0)
  3679         (HHGear^.Damage <> 0)
  3543         //or CheckGearDrowning(HHGear)
  3680         //or CheckGearDrowning(HHGear)
  3544         or (cWaterLine + 512 < hwRound(HHGear^.Y))
  3681         or (cWaterLine + 512 < hwRound(HHGear^.Y))
  3545         or (TurnTimeLeft = 0)
  3682         or (TurnTimeLeft = 0)
  3546         // allow brief ground touches - to be fair on this, might need another counter
  3683         // allow brief ground touches - to be fair on this, might need another counter
  3547         or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
  3684         or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
  3548         or ((Gear^.Message and gmAttack) <> 0) then
  3685         or ((Gear^.Message and gmAttack) <> 0) then
  3549         begin
  3686             begin
  3550         with HHGear^ do
  3687             with HHGear^ do
  3551             begin
  3688                 begin
  3552             Message := 0;
  3689                 Message := 0;
  3553             Active := true;
  3690                 Active := true;
  3554             State := State or gstMoving
  3691                 State := State or gstMoving
  3555             end;
  3692                 end;
  3556         DeleteGear(Gear);
  3693             DeleteGear(Gear);
  3557         isCursorVisible := false;
  3694             isCursorVisible := false;
  3558         ApplyAmmoChanges(HHGear^.Hedgehog^);
  3695             ApplyAmmoChanges(HHGear^.Hedgehog^);
  3559         //    if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
  3696         //    if Gear^.Tex <> nil then FreeTexture(Gear^.Tex);
  3560 
  3697 
  3561 //    Gear^.Tex:= RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(round(Gear^.Health / 20)) + '%', cWhiteColor, fntSmall)
  3698 //    Gear^.Tex:= RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(round(Gear^.Health / 20)) + '%', cWhiteColor, fntSmall)
  3562 
  3699 
  3563 //AddCaption(trmsg[sidFuel]+': '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate);
  3700 //AddCaption(trmsg[sidFuel]+': '+inttostr(round(Gear^.Health/20))+'%', cWhiteColor, capgrpAmmostate);
  3564         end
  3701             end
  3565 end;
  3702 end;
  3566 
  3703 
  3567 procedure doStepJetpack(Gear: PGear);
  3704 procedure doStepJetpack(Gear: PGear);
  3568 var 
  3705 var 
  3569     HHGear: PGear;
  3706     HHGear: PGear;
  3573 
  3710 
  3574     HHGear := Gear^.Hedgehog^.Gear;
  3711     HHGear := Gear^.Hedgehog^.Gear;
  3575     FollowGear := HHGear;
  3712     FollowGear := HHGear;
  3576     AfterAttack;
  3713     AfterAttack;
  3577     with HHGear^ do
  3714     with HHGear^ do
  3578     begin
  3715         begin
  3579         State := State and (not gstAttacking);
  3716         State := State and (not gstAttacking);
  3580         Message := Message and (not (gmAttack or gmUp or gmPrecise or gmLeft or gmRight));
  3717         Message := Message and (not (gmAttack or gmUp or gmPrecise or gmLeft or gmRight));
       
  3718         
  3581         if (dY < _0_1) and (dY > -_0_1) then
  3719         if (dY < _0_1) and (dY > -_0_1) then
  3582         begin
  3720             begin
  3583             Gear^.State := Gear^.State or gsttmpFlag;
  3721             Gear^.State := Gear^.State or gsttmpFlag;
  3584             dY := dY - _0_2
  3722             dY := dY - _0_2
       
  3723             end
  3585         end
  3724         end
  3586     end
       
  3587 end;
  3725 end;
  3588 
  3726 
  3589 ////////////////////////////////////////////////////////////////////////////////
  3727 ////////////////////////////////////////////////////////////////////////////////
  3590 procedure doStepBirdyDisappear(Gear: PGear);
  3728 procedure doStepBirdyDisappear(Gear: PGear);
  3591 begin
  3729 begin
  3592     AllInactive := false;
  3730     AllInactive := false;
  3593     Gear^.Pos := 0;
  3731     Gear^.Pos := 0;
  3594     if Gear^.Timer < 2000 then
  3732     if Gear^.Timer < 2000 then
  3595         inc(Gear^.Timer, 1)
  3733         inc(Gear^.Timer, 1)
  3596     else
  3734     else
  3597     begin
  3735         begin
  3598         DeleteGear(Gear);
  3736         DeleteGear(Gear);
  3599     end;
  3737         end;
  3600 end;
  3738 end;
  3601 
  3739 
  3602 procedure doStepBirdyFly(Gear: PGear);
  3740 procedure doStepBirdyFly(Gear: PGear);
  3603 var 
  3741 var 
  3604     HHGear: PGear;
  3742     HHGear: PGear;
  3616     fuel := 50;
  3754     fuel := 50;
  3617 
  3755 
  3618     if Gear^.Pos > 0 then
  3756     if Gear^.Pos > 0 then
  3619         dec(Gear^.Pos, 1)
  3757         dec(Gear^.Pos, 1)
  3620     else if (HHGear^.Message and (gmLeft or gmRight or gmUp)) <> 0 then
  3758     else if (HHGear^.Message and (gmLeft or gmRight or gmUp)) <> 0 then
  3621              Gear^.Pos := 500;
  3759             Gear^.Pos := 500;
  3622 
  3760 
  3623     if HHGear^.dX.isNegative then
  3761     if HHGear^.dX.isNegative then
  3624         Gear^.Tag := -1
  3762         Gear^.Tag := -1
  3625     else
  3763     else
  3626         Gear^.Tag := 1;
  3764         Gear^.Tag := 1;
  3627 
  3765 
  3628     if (HHGear^.Message and gmUp) <> 0 then
  3766     if (HHGear^.Message and gmUp) <> 0 then
  3629         begin
  3767         begin
  3630         if (not HHGear^.dY.isNegative) or (HHGear^.Y > -_256) then
  3768         if (not HHGear^.dY.isNegative)
       
  3769         or (HHGear^.Y > -_256) then
  3631             HHGear^.dY := HHGear^.dY - move;
  3770             HHGear^.dY := HHGear^.dY - move;
       
  3771             
  3632         dec(Gear^.Health, fuel);
  3772         dec(Gear^.Health, fuel);
  3633         Gear^.MsgParam := Gear^.MsgParam or gmUp;
  3773         Gear^.MsgParam := Gear^.MsgParam or gmUp;
  3634         end;
  3774         end;
       
  3775         
  3635     if (HHGear^.Message and gmLeft) <> 0 then move.isNegative := true;
  3776     if (HHGear^.Message and gmLeft) <> 0 then move.isNegative := true;
  3636     if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then
  3777     if (HHGear^.Message and (gmLeft or gmRight)) <> 0 then
  3637         begin
  3778         begin
  3638         HHGear^.dX := HHGear^.dX + (move * _0_1);
  3779         HHGear^.dX := HHGear^.dX + (move * _0_1);
  3639         dec(Gear^.Health, fuel div 5);
  3780         dec(Gear^.Health, fuel div 5);
  3640         Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight));
  3781         Gear^.MsgParam := Gear^.MsgParam or (HHGear^.Message and (gmLeft or gmRight));
  3641         end;
  3782         end;
  3642 
  3783 
  3643     if Gear^.Health < 0 then Gear^.Health := 0;
  3784     if Gear^.Health < 0 then
       
  3785         Gear^.Health := 0;
       
  3786         
  3644     if ((GameTicks and $FF) = 0) and (Gear^.Health < 500) then
  3787     if ((GameTicks and $FF) = 0) and (Gear^.Health < 500) then
  3645         for i:= ((500-Gear^.Health) div 250) downto 0 do
  3788         for i:= ((500-Gear^.Health) div 250) downto 0 do
  3646             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFeather);
  3789             AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtFeather);
  3647 
  3790 
  3648     if (HHGear^.Message and gmAttack <> 0) then
  3791     if (HHGear^.Message and gmAttack <> 0) then
  3656             end;
  3799             end;
  3657         end;
  3800         end;
  3658 
  3801 
  3659     if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then
  3802     if HHGear^.Message and (gmUp or gmPrecise or gmLeft or gmRight) <> 0 then
  3660         Gear^.State := Gear^.State and (not gsttmpFlag);
  3803         Gear^.State := Gear^.State and (not gsttmpFlag);
       
  3804         
  3661     HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
  3805     HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
  3662     HHGear^.State := HHGear^.State or gstMoving;
  3806     HHGear^.State := HHGear^.State or gstMoving;
  3663 
  3807 
  3664     Gear^.X := HHGear^.X;
  3808     Gear^.X := HHGear^.X;
  3665     Gear^.Y := HHGear^.Y - int2hwFloat(32);
  3809     Gear^.Y := HHGear^.Y - int2hwFloat(32);
  3666     // For some reason I need to reapply followgear here, something else grabs it otherwise.
  3810     // For some reason I need to reapply followgear here, something else grabs it otherwise.
  3667     // this is probably not needed anymore
  3811     // this is probably not needed anymore
  3668     if not CurrentTeam^.ExtDriven then FollowGear := HHGear;
  3812     if not CurrentTeam^.ExtDriven then FollowGear := HHGear;
  3669 
  3813 
  3670     if ((Gear^.State and gsttmpFlag) = 0) or (HHGear^.dY < _0) then doStepHedgehogMoving(HHGear);
  3814     if ((Gear^.State and gsttmpFlag) = 0)
       
  3815     or (HHGear^.dY < _0) then
       
  3816         doStepHedgehogMoving(HHGear);
  3671 
  3817 
  3672     if  (Gear^.Health = 0)
  3818     if  (Gear^.Health = 0)
  3673        or (HHGear^.Damage <> 0)
  3819         or (HHGear^.Damage <> 0)
  3674        or CheckGearDrowning(HHGear)
  3820         or CheckGearDrowning(HHGear)
  3675        or (TurnTimeLeft = 0)
  3821         or (TurnTimeLeft = 0)
  3676        // allow brief ground touches - to be fair on this, might need another counter
  3822         // allow brief ground touches - to be fair on this, might need another counter
  3677        or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
  3823         or (((GameTicks and $1FF) = 0) and (not HHGear^.dY.isNegative) and (TestCollisionYwithGear(HHGear, 1) <> 0))
  3678        or ((Gear^.Message and gmAttack) <> 0) then
  3824         or ((Gear^.Message and gmAttack) <> 0) then
  3679         begin
  3825             begin
  3680         with HHGear^ do
  3826             with HHGear^ do
  3681             begin
  3827                 begin
  3682             Message := 0;
  3828                 Message := 0;
  3683             Active := true;
  3829                 Active := true;
  3684             State := State or gstMoving
  3830                 State := State or gstMoving
  3685             end;
  3831                 end;
  3686         Gear^.State := Gear^.State or gstAnimation or gstTmpFlag;
  3832             Gear^.State := Gear^.State or gstAnimation or gstTmpFlag;
  3687         if HHGear^.dY < _0 then
  3833             if HHGear^.dY < _0 then
  3688             begin
  3834                 begin
  3689             Gear^.dX := HHGear^.dX;
  3835                 Gear^.dX := HHGear^.dX;
  3690             Gear^.dY := HHGear^.dY;
  3836                 Gear^.dY := HHGear^.dY;
  3691             end;
  3837                 end;
  3692         Gear^.Timer := 0;
  3838             Gear^.Timer := 0;
  3693         Gear^.doStep := @doStepBirdyDisappear;
  3839             Gear^.doStep := @doStepBirdyDisappear;
  3694         CurAmmoGear := nil;
  3840             CurAmmoGear := nil;
  3695         isCursorVisible := false;
  3841             isCursorVisible := false;
  3696         AfterAttack;
  3842             AfterAttack;
  3697         end
  3843             end
  3698 end;
  3844 end;
  3699 
  3845 
  3700 procedure doStepBirdyDescend(Gear: PGear);
  3846 procedure doStepBirdyDescend(Gear: PGear);
  3701 var 
  3847 var 
  3702     HHGear: PGear;
  3848     HHGear: PGear;
  3703 begin
  3849 begin
  3704     if Gear^.Timer > 0 then
  3850     if Gear^.Timer > 0 then
  3705         dec(Gear^.Timer, 1)
  3851         dec(Gear^.Timer, 1)
  3706     else if Gear^.Hedgehog^.Gear = nil then
  3852     else if Gear^.Hedgehog^.Gear = nil then
  3707         begin
  3853         begin
  3708             DeleteGear(Gear);
  3854         DeleteGear(Gear);
  3709             AfterAttack;
  3855         AfterAttack;
  3710             exit
  3856         exit
  3711         end;
  3857         end;
  3712     HHGear := Gear^.Hedgehog^.Gear;
  3858     HHGear := Gear^.Hedgehog^.Gear;
  3713     HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
  3859     HHGear^.Message := HHGear^.Message and (not (gmUp or gmPrecise or gmLeft or gmRight));
  3714     if abs(hwRound(HHGear^.Y - Gear^.Y)) > 32 then
  3860     if abs(hwRound(HHGear^.Y - Gear^.Y)) > 32 then
  3715     begin
  3861         begin
  3716         if Gear^.Timer = 0 then
  3862         if Gear^.Timer = 0 then
  3717             Gear^.Y := Gear^.Y + _0_1
  3863             Gear^.Y := Gear^.Y + _0_1
  3718     end
  3864         end
  3719     else if Gear^.Timer = 0 then
  3865     else if Gear^.Timer = 0 then
  3720         begin
  3866         begin
  3721             Gear^.doStep := @doStepBirdyFly;
  3867         Gear^.doStep := @doStepBirdyFly;
  3722             HHGear^.dY := -_0_2
  3868         HHGear^.dY := -_0_2
  3723         end
  3869         end
  3724 end;
  3870 end;
  3725 
  3871 
  3726 procedure doStepBirdyAppear(Gear: PGear);
  3872 procedure doStepBirdyAppear(Gear: PGear);
  3727 begin
  3873 begin
  3728     Gear^.Pos := 0;
  3874     Gear^.Pos := 0;
  3729     if Gear^.Timer < 2000 then
  3875     if Gear^.Timer < 2000 then
  3730         inc(Gear^.Timer, 1)
  3876         inc(Gear^.Timer, 1)
  3731     else
  3877     else
  3732     begin
  3878         begin
  3733         Gear^.Timer := 500;
  3879         Gear^.Timer := 500;
  3734         Gear^.dX := _0;
  3880         Gear^.dX := _0;
  3735         Gear^.dY := _0;
  3881         Gear^.dY := _0;
  3736         Gear^.State :=  Gear^.State and (not gstAnimation);
  3882         Gear^.State :=  Gear^.State and (not gstAnimation);
  3737         Gear^.doStep := @doStepBirdyDescend;
  3883         Gear^.doStep := @doStepBirdyDescend;
  3738     end
  3884         end
  3739 end;
  3885 end;
  3740 
  3886 
  3741 procedure doStepBirdy(Gear: PGear);
  3887 procedure doStepBirdy(Gear: PGear);
  3742 var 
  3888 var 
  3743     HHGear: PGear;
  3889     HHGear: PGear;
  3744 begin
  3890 begin
  3745     gear^.State :=  gear^.State or gstAnimation and (not gstTmpFlag);
  3891     gear^.State :=  gear^.State or gstAnimation and (not gstTmpFlag);
  3746     Gear^.doStep := @doStepBirdyAppear;
  3892     Gear^.doStep := @doStepBirdyAppear;
       
  3893     
  3747     if CurrentHedgehog = nil then
  3894     if CurrentHedgehog = nil then
  3748     begin
  3895         begin
  3749         DeleteGear(Gear);
  3896         DeleteGear(Gear);
  3750         exit
  3897         exit
  3751     end;
  3898         end;
  3752 
  3899 
  3753     HHGear := CurrentHedgehog^.Gear;
  3900     HHGear := CurrentHedgehog^.Gear;
  3754 
  3901 
  3755     if HHGear^.dX.isNegative then
  3902     if HHGear^.dX.isNegative then
  3756         Gear^.Tag := -1
  3903         Gear^.Tag := -1
  3777     doStepFallingGear(Gear);
  3924     doStepFallingGear(Gear);
  3778     //    CheckGearDrowning(Gear); // already checked for in doStepFallingGear
  3925     //    CheckGearDrowning(Gear); // already checked for in doStepFallingGear
  3779     CalcRotationDirAngle(Gear);
  3926     CalcRotationDirAngle(Gear);
  3780 
  3927 
  3781     if (Gear^.State and gstCollision) <> 0 then
  3928     if (Gear^.State and gstCollision) <> 0 then
  3782     begin
  3929         begin
  3783         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 10, Gear^.Hedgehog, EXPLPoisoned, $C0E0FFE0);
  3930         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 10, Gear^.Hedgehog, EXPLPoisoned, $C0E0FFE0);
  3784         PlaySound(sndEggBreak);
  3931         PlaySound(sndEggBreak);
  3785         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
  3932         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
  3786         vg := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
  3933         vg := AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtEgg);
  3787         if vg <> nil then vg^.Frame := 2;
  3934         if vg <> nil then
       
  3935             vg^.Frame := 2;
  3788 
  3936 
  3789         for i:= 10 downto 0 do
  3937         for i:= 10 downto 0 do
  3790         begin
  3938             begin
  3791             vg := AddVisualGear(hwRound(Gear^.X) - 3 + Random(6), hwRound(Gear^.Y) - 3 + Random(6),
  3939             vg := AddVisualGear(hwRound(Gear^.X) - 3 + Random(6), hwRound(Gear^.Y) - 3 + Random(6),
  3792                   vgtDust);
  3940                   vgtDust);
  3793             if vg <> nil then vg^.dX := vg^.dX + (Gear^.dX.QWordValue / 21474836480);
  3941             if vg <> nil then
  3794         end;
  3942                 vg^.dX := vg^.dX + (Gear^.dX.QWordValue / 21474836480);
       
  3943             end;
  3795 
  3944 
  3796         DeleteGear(Gear);
  3945         DeleteGear(Gear);
  3797         exit
  3946         exit
  3798     end;
  3947         end;
  3799 end;
  3948 end;
  3800 
  3949 
  3801 ////////////////////////////////////////////////////////////////////////////////
  3950 ////////////////////////////////////////////////////////////////////////////////
  3802 procedure doPortalColorSwitch();
  3951 procedure doPortalColorSwitch();
  3803 var CurWeapon: PAmmo;
  3952 var CurWeapon: PAmmo;
  3804 begin
  3953 begin
  3805     if (CurrentHedgehog <> nil)
  3954     if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then
  3806        and (CurrentHedgehog^.Gear <> nil)
  3955             with CurrentHedgehog^ do
  3807        and ((CurrentHedgehog^.Gear^.Message and gmSwitch) <> 0) then
  3956                 if (CurAmmoType = amPortalGun) then
  3808         with CurrentHedgehog^ do
  3957                     begin
  3809             if (CurAmmoType = amPortalGun) then
  3958                     CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSwitch);
  3810             begin
       
  3811                 CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSwitch);
       
  3812                 
  3959                 
  3813                 CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
  3960                     CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
  3814                 if CurWeapon^.Pos <> 0 then
  3961                     if CurWeapon^.Pos <> 0 then
  3815                     CurWeapon^.Pos := 0
  3962                         CurWeapon^.Pos := 0
  3816                 else
  3963                         
       
  3964                     else
  3817                     CurWeapon^.Pos := 1;
  3965                     CurWeapon^.Pos := 1;
  3818             end;
  3966                     end;
  3819 end;
  3967 end;
  3820 
  3968 
  3821 procedure doStepPortal(Gear: PGear);
  3969 procedure doStepPortal(Gear: PGear);
  3822 var 
  3970 var 
  3823     iterator, conPortal: PGear;
  3971     iterator, conPortal: PGear;
  3828 begin
  3976 begin
  3829     doPortalColorSwitch();
  3977     doPortalColorSwitch();
  3830 
  3978 
  3831     // destroy portal if ground it was attached too is gone
  3979     // destroy portal if ground it was attached too is gone
  3832     if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
  3980     if ((Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0)
  3833        or (Gear^.Timer < 1)
  3981     or (Gear^.Timer < 1)
  3834        or (Gear^.Hedgehog^.Team <> CurrentHedgehog^.Team)
  3982     or (Gear^.Hedgehog^.Team <> CurrentHedgehog^.Team)
  3835        or (hwRound(Gear^.Y) > cWaterLine) then
  3983     or (hwRound(Gear^.Y) > cWaterLine) then
  3836     begin
  3984         begin
  3837         deleteGear(Gear);
  3985         deleteGear(Gear);
  3838         EXIT;
  3986         EXIT;
  3839     end;
  3987         end;
  3840 
  3988 
  3841     if (TurnTimeLeft < 1)
  3989     if (TurnTimeLeft < 1)
  3842        or (Gear^.Health < 1) then
  3990     or (Gear^.Health < 1) then
  3843         dec(Gear^.Timer);
  3991         dec(Gear^.Timer);
  3844 
  3992 
  3845     if Gear^.Timer < 10000 then
  3993     if Gear^.Timer < 10000 then
  3846         gear^.RenderTimer := true;
  3994         gear^.RenderTimer := true;
  3847 
  3995 
  3868         if iterator = nil then
  4016         if iterator = nil then
  3869             break;
  4017             break;
  3870 
  4018 
  3871         // don't port portals or other gear that wouldn't make sense
  4019         // don't port portals or other gear that wouldn't make sense
  3872         if (iterator^.Kind in [gtPortal, gtRope, gtRCPlane])
  4020         if (iterator^.Kind in [gtPortal, gtRope, gtRCPlane])
  3873             or (iterator^.PortalCounter > 32) then
  4021         or (iterator^.PortalCounter > 32) then
  3874              continue;
  4022             continue;
  3875 
  4023 
  3876         // don't port hogs on rope
  4024         // don't port hogs on rope
  3877         // TODO: this will also prevent hogs while falling after rope use from
  4025         // TODO: this will also prevent hogs while falling after rope use from
  3878         //       falling through portals... fix that!
  4026         //       falling through portals... fix that!
  3879 
  4027 
  3884         // this is the max range we accept incoming gears in
  4032         // this is the max range we accept incoming gears in
  3885         r := Int2hwFloat(iterator^.Radius+Gear^.Radius);
  4033         r := Int2hwFloat(iterator^.Radius+Gear^.Radius);
  3886 
  4034 
  3887         // too far away?
  4035         // too far away?
  3888         if (iterator^.X < Gear^.X - r)
  4036         if (iterator^.X < Gear^.X - r)
  3889            or (iterator^.X > Gear^.X + r)
  4037         or (iterator^.X > Gear^.X + r)
  3890            or (iterator^.Y < Gear^.Y - r)
  4038         or (iterator^.Y < Gear^.Y - r)
  3891            or (iterator^.Y > Gear^.Y + r) then
  4039         or (iterator^.Y > Gear^.Y + r) then
  3892             continue;
  4040             continue;
  3893 
  4041 
  3894         hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0))
  4042         hasdxy := (((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0)) or ((iterator^.State or gstMoving) = 0));
  3895                     or ((iterator^.State or gstMoving) = 0));
       
  3896 
  4043 
  3897         // in case the object is not moving, let's asume it's falling towards the portal
  4044         // in case the object is not moving, let's asume it's falling towards the portal
  3898         if not hasdxy then
  4045         if not hasdxy then
  3899         begin
  4046             begin
  3900             if Gear^.Y < iterator^.Y then
  4047             if Gear^.Y < iterator^.Y then
  3901                 continue;
  4048                 continue;
  3902             ox:= Gear^.X - iterator^.X;
  4049             ox:= Gear^.X - iterator^.X;
  3903             oy:= Gear^.Y - iterator^.Y;
  4050             oy:= Gear^.Y - iterator^.Y;
  3904         end
  4051             end
  3905         else
  4052         else
  3906         begin
  4053             begin
  3907             ox:= iterator^.dX;
  4054             ox:= iterator^.dX;
  3908             oy:= iterator^.dY;
  4055             oy:= iterator^.dY;
  3909         end;
  4056             end;
  3910 
  4057 
  3911         // cake will need extra treatment... it's so delicious and moist!
  4058         // cake will need extra treatment... it's so delicious and moist!
  3912         iscake:= (iterator^.Kind = gtCake);
  4059         iscake:= (iterator^.Kind = gtCake);
  3913 
  4060 
  3914         // won't port stuff that does not move towards the front/portal entrance
  4061         // won't port stuff that does not move towards the front/portal entrance
  3915         if iscake then
  4062         if iscake then
  3916         begin
  4063             begin
  3917             if not (((iterator^.X - Gear^.X)*ox + (iterator^.Y - Gear^.Y)*oy).isNegative) then
  4064             if not (((iterator^.X - Gear^.X)*ox + (iterator^.Y - Gear^.Y)*oy).isNegative) then
  3918                 continue;
  4065                 continue;
  3919         end
  4066             end
  3920         else
  4067         else
  3921             if not ((Gear^.dX*ox + Gear^.dY*oy).isNegative) then
  4068             if not ((Gear^.dX*ox + Gear^.dY*oy).isNegative) then
  3922                 continue;
  4069                 continue;
  3923 
  4070 
  3924         isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]);
  4071         isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]);
  3925 
  4072 
  3926         r:= int2hwFloat(iterator^.Radius);
  4073         r:= int2hwFloat(iterator^.Radius);
  3927 
  4074 
  3928         if not (isbullet or iscake) then
  4075         if not (isbullet or iscake) then
  3929         begin
  4076             begin
  3930             // wow! good candidate there, let's see if the distance and direction is okay!
  4077             // wow! good candidate there, let's see if the distance and direction is okay!
  3931             if hasdxy then
  4078             if hasdxy then
  3932             begin
  4079                 begin
  3933                 s := r / Distance(iterator^.dX, iterator^.dY);
  4080                 s := r / Distance(iterator^.dX, iterator^.dY);
  3934                 ox:= iterator^.X + s * iterator^.dX;
  4081                 ox:= iterator^.X + s * iterator^.dX;
  3935                 oy:= iterator^.Y + s * iterator^.dY;
  4082                 oy:= iterator^.Y + s * iterator^.dY;
  3936             end
  4083                 end
  3937             else
  4084             else
  3938             begin
  4085                 begin
  3939                 ox:= iterator^.X;
  4086                 ox:= iterator^.X;
  3940                 oy:= iterator^.Y + r;
  4087                 oy:= iterator^.Y + r;
  3941             end;
  4088                 end;
  3942 
  4089 
  3943             if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then
  4090             if (hwRound(Distance(Gear^.X-ox,Gear^.Y-oy)) > Gear^.Radius + 1 ) then
  3944                 continue;
  4091                 continue;
  3945         end;
  4092             end;
  3946 
  4093 
  3947         // draw bullet trail
  4094         // draw bullet trail
  3948         if isbullet then
  4095         if isbullet then
  3949             spawnBulletTrail(iterator);
  4096             spawnBulletTrail(iterator);
  3950 
  4097 
  3987 
  4134 
  3988         if isBullet and (hwRound(hwAbs(noffs)) >= Gear^.Radius) then
  4135         if isBullet and (hwRound(hwAbs(noffs)) >= Gear^.Radius) then
  3989             continue;
  4136             continue;
  3990 
  4137 
  3991         // avoid gravity related loops of not really moving gear
  4138         // avoid gravity related loops of not really moving gear
  3992         if not (iscake or isbullet) and (Gear^.dY.isNegative) and (conPortal^.dY.isNegative)
  4139         if not (iscake or isbullet)
  3993             and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
  4140         and (Gear^.dY.isNegative)
  3994             and (iterator^.PortalCounter > 0) then
  4141         and (conPortal^.dY.isNegative)
  3995              continue;
  4142         and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
       
  4143         and (iterator^.PortalCounter > 0) then
       
  4144             continue;
  3996 
  4145 
  3997         // calc gear speed along to the vector and the normal vector of the portal
  4146         // calc gear speed along to the vector and the normal vector of the portal
  3998         if hasdxy then
  4147         if hasdxy then
  3999         begin
  4148             begin
  4000             pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY);
  4149             pspeed:= (Gear^.dX * iterator^.dX + Gear^.dY * iterator^.dY);
  4001             nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
  4150             nspeed:= (nx * iterator^.dX + ny * iterator^.dY);
  4002         end
  4151             end
  4003         else
  4152         else
  4004         begin
  4153             begin
  4005             pspeed:= hwAbs(cGravity * oy);
  4154             pspeed:= hwAbs(cGravity * oy);
  4006             nspeed:= _0;
  4155             nspeed:= _0;
  4007         end;
  4156             end;
  4008 
  4157 
  4009         // creating normal vector of connected (exit) portal
  4158         // creating normal vector of connected (exit) portal
  4010         nx := conPortal^.dY;
  4159         nx := conPortal^.dY;
  4011         ny := conPortal^.dX;
  4160         ny := conPortal^.dX;
  4012         if conPortal^.Elasticity.isNegative then
  4161         if conPortal^.Elasticity.isNegative then
  4023         iterator^.dY := -pspeed * conPortal^.dY + nspeed * ny;
  4172         iterator^.dY := -pspeed * conPortal^.dY + nspeed * ny;
  4024 
  4173 
  4025         // make the gear's exit position close to the portal while
  4174         // make the gear's exit position close to the portal while
  4026         // still respecting the movement direction
  4175         // still respecting the movement direction
  4027 
  4176 
  4028          // determine the distance (in exit vector direction)
  4177         // determine the distance (in exit vector direction)
  4029          // that we want the gear at
  4178         // that we want the gear at
  4030          if iscake then
  4179         if iscake then
  4031              ox:= (r - _0_7)
  4180             ox:= (r - _0_7)
  4032          else
  4181         else
  4033              ox:= (r * _1_5);
  4182             ox:= (r * _1_5);
  4034          s:= ox / poffs;
  4183         s:= ox / poffs;
  4035          poffs:= ox;
  4184         poffs:= ox;
  4036          if (nspeed.QWordValue <> 0) and (pspeed > _0) then
  4185         if (nspeed.QWordValue <> 0)
  4037              noffs:= noffs * s * (nspeed / pspeed);
  4186         and (pspeed > _0) then
       
  4187             noffs:= noffs * s * (nspeed / pspeed);
  4038 
  4188 
  4039         // move stuff with high normal offset closer to the portal's center
  4189         // move stuff with high normal offset closer to the portal's center
  4040         if not isbullet then
  4190         if not isbullet then
  4041         begin
  4191             begin
  4042             s := hwAbs(noffs) + r - int2hwFloat(Gear^.Radius);
  4192             s := hwAbs(noffs) + r - int2hwFloat(Gear^.Radius);
  4043             if s > _0 then
  4193             if s > _0 then
  4044                 noffs:= noffs - SignAs(s,noffs)
  4194                 noffs:= noffs - SignAs(s,noffs)
  4045         end;
  4195             end;
  4046 
  4196 
  4047         iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx;
  4197         iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx;
  4048         iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny;
  4198         iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny;
  4049 
  4199 
  4050         if not hasdxy and (not (conPortal^.dY.isNegative)) then
  4200         if not hasdxy and (not (conPortal^.dY.isNegative)) then
  4051         begin
  4201             begin
  4052             iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
  4202             iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
  4053         end;
  4203             end;
  4054 
  4204 
  4055         // see if the space on the exit side actually is enough
  4205         // see if the space on the exit side actually is enough
  4056 
  4206 
  4057         if not (isBullet or isCake) then
  4207         if not (isBullet or isCake) then
  4058         begin
  4208             begin
  4059             // TestCollisionXwithXYShift requires a hwFloat for xShift
  4209             // TestCollisionXwithXYShift requires a hwFloat for xShift
  4060             ox.QWordValue := _1.QWordValue;
  4210             ox.QWordValue := _1.QWordValue;
  4061             ox.isNegative := not iterator^.dX.isNegative;
  4211             ox.isNegative := not iterator^.dX.isNegative;
  4062 
  4212 
  4063             sx := hwSign(iterator^.dX);
  4213             sx := hwSign(iterator^.dX);
  4069             // check front
  4219             // check front
  4070             isCollision := TestCollisionY(iterator, sy)
  4220             isCollision := TestCollisionY(iterator, sy)
  4071                         or TestCollisionX(iterator, sx);
  4221                         or TestCollisionX(iterator, sx);
  4072 
  4222 
  4073             if not isCollision then
  4223             if not isCollision then
  4074             begin
  4224                 begin
  4075                 // check center area (with half the radius so that the
  4225                 // check center area (with half the radius so that the
  4076                 // the square check won't check more pixels than we want to)
  4226                 // the square check won't check more pixels than we want to)
  4077                 iterator^.Radius := 1 + resetr div 2;
  4227                 iterator^.Radius := 1 + resetr div 2;
  4078                 rh := resetr div 4;
  4228                 rh := resetr div 4;
  4079                 isCollision := TestCollisionYwithXYShift(iterator,       0, -sy * rh, sy, false)
  4229                 isCollision := TestCollisionYwithXYShift(iterator,       0, -sy * rh, sy, false)
  4080                             or TestCollisionXwithXYShift(iterator, ox * rh,        0, sx, false);
  4230                             or TestCollisionXwithXYShift(iterator, ox * rh,        0, sx, false);
  4081             end;
  4231                 end;
  4082 
  4232 
  4083             iterator^.Radius := resetr;
  4233             iterator^.Radius := resetr;
  4084 
  4234 
  4085             if isCollision then
  4235             if isCollision then
  4086             begin
  4236                 begin
  4087                 // collision! oh crap! go back!
  4237                 // collision! oh crap! go back!
  4088                 iterator^.X  := resetx;
  4238                 iterator^.X  := resetx;
  4089                 iterator^.Y  := resety;
  4239                 iterator^.Y  := resety;
  4090                 iterator^.dX := resetdx;
  4240                 iterator^.dX := resetdx;
  4091                 iterator^.dY := resetdy;
  4241                 iterator^.dY := resetdy;
  4092                 continue;
  4242                 continue;
  4093             end;
  4243                 end;
  4094         end;
  4244             end;
  4095 
  4245 
  4096         //
  4246         //
  4097         // You're now officially portaled!
  4247         // You're now officially portaled!
  4098         //
  4248         //
  4099 
  4249 
  4100         // Until loops are reliably broken
  4250         // Until loops are reliably broken
  4101         if iscake then iterator^.PortalCounter:= 33
  4251         if iscake then
       
  4252             iterator^.PortalCounter:= 33
  4102         else
  4253         else
  4103             begin
  4254             begin
  4104             inc(iterator^.PortalCounter);
  4255             inc(iterator^.PortalCounter);
  4105             iterator^.State:= iterator^.State and (not gstHHHJump)
  4256             iterator^.State:= iterator^.State and (not gstHHHJump)
  4106             end;
  4257             end;
  4107 
  4258 
  4108         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)
  4259         if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil)
  4109            and (iterator = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =
  4260         and (iterator = CurrentHedgehog^.Gear)
  4110            gtRope) then CurAmmoGear^.PortalCounter:= 1;
  4261         and (CurAmmoGear <> nil)
  4111 
  4262         and (CurAmmoGear^.Kind =gtRope) then
  4112         if not isbullet and (iterator^.Kind <> gtFlake) then
  4263                CurAmmoGear^.PortalCounter:= 1;
       
  4264 
       
  4265         if not isbullet
       
  4266         and (iterator^.Kind <> gtFlake) then
  4113             FollowGear := iterator;
  4267             FollowGear := iterator;
  4114 
  4268 
  4115         // store X/Y values of exit for net bullet trail
  4269         // store X/Y values of exit for net bullet trail
  4116         if isbullet then
  4270         if isbullet then
  4117         begin
  4271             begin
  4118             iterator^.Elasticity:= iterator^.X;
  4272             iterator^.Elasticity:= iterator^.X;
  4119             iterator^.Friction  := iterator^.Y;
  4273             iterator^.Friction  := iterator^.Y;
  4120         end;
  4274             end;
  4121 
  4275 
  4122         // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
  4276         // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
  4123         iterator:= GearsList;
  4277         iterator:= GearsList;
  4124         while iterator <> nil do
  4278         while iterator <> nil do
  4125             begin
  4279             begin
  4126             if (iterator^.Kind <> gtPortal) and 
  4280             if (iterator^.Kind <> gtPortal) and ((iterator^.Hedgehog <> CurrentHedgehog)
  4127                ((iterator^.Hedgehog <> CurrentHedgehog) or ((iterator^.Message and gmAllStoppable) = 0)) then
  4281             or ((iterator^.Message and gmAllStoppable) = 0)) then
  4128                 begin
  4282                     begin
  4129                 iterator^.Active:= true;
  4283                     iterator^.Active:= true;
  4130                 if iterator^.dY.QWordValue = _0.QWordValue then iterator^.dY.isNegative:= false;
  4284                     if iterator^.dY.QWordValue = _0.QWordValue then
  4131                 iterator^.State:= iterator^.State or gstMoving;
  4285                         iterator^.dY.isNegative:= false;
  4132                 DeleteCI(iterator);
  4286                     iterator^.State:= iterator^.State or gstMoving;
       
  4287                     DeleteCI(iterator);
  4133                 //inc(iterator^.dY.QWordValue,10);
  4288                 //inc(iterator^.dY.QWordValue,10);
  4134                 end;
  4289                     end;
  4135             iterator:= iterator^.NextGear
  4290             iterator:= iterator^.NextGear
  4136             end;
  4291             end;
  4137 
  4292 
  4138         if Gear^.Health > 1 then dec(Gear^.Health);
  4293         if Gear^.Health > 1 then
       
  4294             dec(Gear^.Health);
  4139     end;
  4295     end;
  4140 end;
  4296 end;
  4141 
  4297 
  4142 
  4298 
  4143 
  4299 
  4162 
  4318 
  4163                 // make the ball visible
  4319                 // make the ball visible
  4164                 CurWeapon^.Timer := 0;
  4320                 CurWeapon^.Timer := 0;
  4165                 end
  4321                 end
  4166             end;
  4322             end;
  4167     if destroyGear then oldPortal^.Timer:= 0;
  4323     if destroyGear then
       
  4324         oldPortal^.Timer:= 0;
  4168 end;
  4325 end;
  4169 
  4326 
  4170 procedure doStepMovingPortal_real(Gear: PGear);
  4327 procedure doStepMovingPortal_real(Gear: PGear);
  4171 var 
  4328 var 
  4172     x, y, tx, ty: LongInt;
  4329     x, y, tx, ty: LongInt;
  4177     tx := 0;
  4334     tx := 0;
  4178     ty := 0;
  4335     ty := 0;
  4179     // avoid compiler hints
  4336     // avoid compiler hints
  4180 
  4337 
  4181     if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then
  4338     if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] > 255) then
  4182     begin
  4339         begin
  4183         Gear^.State := Gear^.State or gstCollision;
  4340         Gear^.State := Gear^.State or gstCollision;
  4184         Gear^.State := Gear^.State and (not gstMoving);
  4341         Gear^.State := Gear^.State and (not gstMoving);
       
  4342         
  4185         if not CalcSlopeTangent(Gear, x, y, tx, ty, 255)
  4343         if not CalcSlopeTangent(Gear, x, y, tx, ty, 255)
  4186            or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
  4344         or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
  4187         begin
  4345             begin
  4188             loadNewPortalBall(Gear, true);
  4346             loadNewPortalBall(Gear, true);
  4189             EXIT;
  4347             EXIT;
  4190         end;
  4348             end;
  4191 
  4349 
  4192         // making a normalized normal vector
  4350         // making a normalized normal vector
  4193         s := _1/DistanceI(tx,ty);
  4351         s := _1/DistanceI(tx,ty);
  4194         Gear^.dX :=  s * ty;
  4352         Gear^.dX :=  s * ty;
  4195         Gear^.dY := -s * tx;
  4353         Gear^.dY := -s * tx;
  4196 
  4354 
  4197         Gear^.DirAngle := DxDy2Angle(-Gear^.dY,Gear^.dX);
  4355         Gear^.DirAngle := DxDy2Angle(-Gear^.dY,Gear^.dX);
  4198         if not Gear^.dX.isNegative then Gear^.DirAngle := 180-Gear^.DirAngle;
  4356         if not Gear^.dX.isNegative then
       
  4357             Gear^.DirAngle := 180-Gear^.DirAngle;
  4199 
  4358 
  4200         if ((Gear^.IntersectGear = nil)
  4359         if ((Gear^.IntersectGear = nil)
  4201            or (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) >=
  4360         or (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) >=Gear^.Radius*2)) then
  4202            Gear^.Radius*2))
  4361             begin
  4203             then
       
  4204         begin
       
  4205             loadNewPortalBall(Gear, false);
  4362             loadNewPortalBall(Gear, false);
  4206             inc(Gear^.Tag);
  4363             inc(Gear^.Tag);
  4207             Gear^.doStep := @doStepPortal;
  4364             Gear^.doStep := @doStepPortal;
  4208         end
  4365         end
  4209         else
  4366         else
  4210             loadNewPortalBall(Gear, true);
  4367             loadNewPortalBall(Gear, true);
  4211     end
  4368     end
  4212     else if (y > cWaterLine) or (y < -LAND_WIDTH)
  4369     
  4213             or (x > 2*LAND_WIDTH) or (x < -LAND_WIDTH) then
  4370     else if (y > cWaterLine)
  4214              loadNewPortalBall(Gear, true);
  4371     or (y < -LAND_WIDTH)
       
  4372     or (x > 2*LAND_WIDTH)
       
  4373     or (x < -LAND_WIDTH) then
       
  4374         loadNewPortalBall(Gear, true);
  4215 end;
  4375 end;
  4216 
  4376 
  4217 procedure doStepMovingPortal(Gear: PGear);
  4377 procedure doStepMovingPortal(Gear: PGear);
  4218 begin
  4378 begin
  4219     doPortalColorSwitch();
  4379     doPortalColorSwitch();
  4220     doStepPerPixel(Gear, @doStepMovingPortal_real, true);
  4380     doStepPerPixel(Gear, @doStepMovingPortal_real, true);
  4221     if (Gear^.Timer < 1) 
  4381     if (Gear^.Timer < 1) 
  4222        or (Gear^.Hedgehog^.Team <> CurrentHedgehog^.Team) then
  4382     or (Gear^.Hedgehog^.Team <> CurrentHedgehog^.Team) then
  4223             deleteGear(Gear);
  4383         deleteGear(Gear);
  4224 end;
  4384 end;
  4225 
  4385 
  4226 procedure doStepPortalShot(newPortal: PGear);
  4386 procedure doStepPortalShot(newPortal: PGear);
  4227 var 
  4387 var 
  4228     iterator: PGear;
  4388     iterator: PGear;
  4241 
  4401 
  4242     newPortal^.IntersectGear := nil;
  4402     newPortal^.IntersectGear := nil;
  4243 
  4403 
  4244     if CurrentHedgehog <> nil then
  4404     if CurrentHedgehog <> nil then
  4245         with CurrentHedgehog^ do
  4405         with CurrentHedgehog^ do
  4246         begin
  4406             begin
  4247             CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
  4407             CurWeapon:= GetAmmoEntry(CurrentHedgehog^);
  4248             // let's save the HH's dX's direction so we can decide where the "top" of the portal hole
  4408             // let's save the HH's dX's direction so we can decide where the "top" of the portal hole
  4249             newPortal^.Elasticity.isNegative := CurrentHedgehog^.Gear^.dX.isNegative;
  4409             newPortal^.Elasticity.isNegative := CurrentHedgehog^.Gear^.dX.isNegative;
  4250             // when doing a backjump the dx is the opposite of the facing direction
  4410             // when doing a backjump the dx is the opposite of the facing direction
  4251             if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then
  4411             if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery) then
  4258             iterator := GearsList;
  4418             iterator := GearsList;
  4259             while iterator <> nil do
  4419             while iterator <> nil do
  4260             begin
  4420             begin
  4261                 if (iterator^.Kind = gtPortal) then
  4421                 if (iterator^.Kind = gtPortal) then
  4262                     if (iterator <> newPortal) and (iterator^.Timer > 0) and (iterator^.Hedgehog = CurrentHedgehog) then
  4422                     if (iterator <> newPortal) and (iterator^.Timer > 0) and (iterator^.Hedgehog = CurrentHedgehog) then
  4263                     begin
  4423                         begin
  4264                         if ((iterator^.Tag and 2) = (newPortal^.Tag and 2)) then
  4424                         if ((iterator^.Tag and 2) = (newPortal^.Tag and 2)) then
  4265                             begin
  4425                             begin
  4266                             iterator^.Timer:= 0;
  4426                             iterator^.Timer:= 0;
  4267                             end
  4427                             end
  4268                         else
  4428                         else
  4270                             // link portals with each other
  4430                             // link portals with each other
  4271                             newPortal^.IntersectGear := iterator;
  4431                             newPortal^.IntersectGear := iterator;
  4272                             iterator^.IntersectGear := newPortal;
  4432                             iterator^.IntersectGear := newPortal;
  4273                             iterator^.Health := newPortal^.Health;
  4433                             iterator^.Health := newPortal^.Health;
  4274                             end;
  4434                             end;
  4275                     end;
  4435                         end;
  4276                 iterator^.PortalCounter:= 0;
  4436                 iterator^.PortalCounter:= 0;
  4277                 iterator := iterator^.NextGear
  4437                 iterator := iterator^.NextGear
  4278             end;
  4438             end;
  4279         end;
  4439             end;
  4280     newPortal^.State := newPortal^.State and (not gstCollision);
  4440     newPortal^.State := newPortal^.State and (not gstCollision);
  4281     newPortal^.State := newPortal^.State or gstMoving;
  4441     newPortal^.State := newPortal^.State or gstMoving;
  4282     newPortal^.doStep := @doStepMovingPortal;
  4442     newPortal^.doStep := @doStepMovingPortal;
  4283 end;
  4443 end;
  4284 
  4444 
  4288     r0, r1: LongInt;
  4448     r0, r1: LongInt;
  4289     odY: hwFloat;
  4449     odY: hwFloat;
  4290 begin
  4450 begin
  4291     AllInactive := false;
  4451     AllInactive := false;
  4292     if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and 
  4452     if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Gear <> nil) and 
  4293        ((CurrentHedgehog^.Gear^.Message and gmSlot) <> 0) then
  4453         ((CurrentHedgehog^.Gear^.Message and gmSlot) <> 0) then
  4294         begin
  4454             begin
  4295         case CurrentHedgehog^.Gear^.MsgParam of 
  4455                 case CurrentHedgehog^.Gear^.MsgParam of 
  4296             0: PlaySound(sndPiano0);
  4456                 0: PlaySound(sndPiano0);
  4297             1: PlaySound(sndPiano1);
  4457                 1: PlaySound(sndPiano1);
  4298             2: PlaySound(sndPiano2);
  4458                 2: PlaySound(sndPiano2);
  4299             3: PlaySound(sndPiano3);
  4459                 3: PlaySound(sndPiano3);
  4300             4: PlaySound(sndPiano4);
  4460                 4: PlaySound(sndPiano4);
  4301             5: PlaySound(sndPiano5);
  4461                 5: PlaySound(sndPiano5);
  4302             6: PlaySound(sndPiano6);
  4462                 6: PlaySound(sndPiano6);
  4303             7: PlaySound(sndPiano7);
  4463                 7: PlaySound(sndPiano7);
  4304             else PlaySound(sndPiano8);
  4464                 else PlaySound(sndPiano8);
  4305         end;
  4465             end;
  4306         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote);
  4466         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtNote);
  4307         CurrentHedgehog^.Gear^.MsgParam := 0;
  4467         CurrentHedgehog^.Gear^.MsgParam := 0;
  4308         CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSlot);
  4468         CurrentHedgehog^.Gear^.Message := CurrentHedgehog^.Gear^.Message and (not gmSlot);
  4309         end;
  4469         end;
  4310 
  4470 
  4321                 // Drown the hedgehog.  Could also just delete it, but hey, this gets a caption
  4481                 // Drown the hedgehog.  Could also just delete it, but hey, this gets a caption
  4322                 CurrentHedgehog^.Gear^.Active := true;
  4482                 CurrentHedgehog^.Gear^.Active := true;
  4323                 CurrentHedgehog^.Gear^.X := Gear^.X;
  4483                 CurrentHedgehog^.Gear^.X := Gear^.X;
  4324                 CurrentHedgehog^.Gear^.Y := int2hwFloat(cWaterLine+cVisibleWater)+_128;
  4484                 CurrentHedgehog^.Gear^.Y := int2hwFloat(cWaterLine+cVisibleWater)+_128;
  4325                 CurrentHedgehog^.Unplaced := false;
  4485                 CurrentHedgehog^.Unplaced := false;
  4326                 if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft;
  4486                 if TagTurnTimeLeft = 0 then
       
  4487                     TagTurnTimeLeft:= TurnTimeLeft;
  4327                 TurnTimeLeft:= 0
  4488                 TurnTimeLeft:= 0
  4328                 end;
  4489                 end;
  4329             ResumeMusic
  4490             ResumeMusic
  4330             end;
  4491             end;
  4331         exit
  4492         exit
  4342             // Drown the hedgehog.  Could also just delete it, but hey, this gets a caption
  4503             // Drown the hedgehog.  Could also just delete it, but hey, this gets a caption
  4343             CurrentHedgehog^.Gear^.Active := true;
  4504             CurrentHedgehog^.Gear^.Active := true;
  4344             CurrentHedgehog^.Gear^.X := Gear^.X;
  4505             CurrentHedgehog^.Gear^.X := Gear^.X;
  4345             CurrentHedgehog^.Gear^.Y := int2hwFloat(cWaterLine+cVisibleWater)+_128;
  4506             CurrentHedgehog^.Gear^.Y := int2hwFloat(cWaterLine+cVisibleWater)+_128;
  4346             CurrentHedgehog^.Unplaced := false;
  4507             CurrentHedgehog^.Unplaced := false;
  4347             if TagTurnTimeLeft = 0 then TagTurnTimeLeft:= TurnTimeLeft;
  4508             if TagTurnTimeLeft = 0 then
       
  4509                 TagTurnTimeLeft:= TurnTimeLeft;
  4348             TurnTimeLeft:= 0
  4510             TurnTimeLeft:= 0
  4349             end;
  4511             end;
  4350         ResumeMusic
  4512         ResumeMusic
  4351         end
  4513         end
  4352     else if (Gear^.State and gstCollision) <> 0 then
  4514     else if (Gear^.State and gstCollision) <> 0 then
  4384     ldX := ldX * sdy;
  4546     ldX := ldX * sdy;
  4385     ldY := ldY * sdy;
  4547     ldY := ldY * sdy;
  4386     sdY := hwAbs(ldX) + hwAbs(ldY);
  4548     sdY := hwAbs(ldX) + hwAbs(ldY);
  4387     sdX := _1 - hwAbs(ldX/sdY);
  4549     sdX := _1 - hwAbs(ldX/sdY);
  4388     sdY := _1 - hwAbs(ldY/sdY);
  4550     sdY := _1 - hwAbs(ldY/sdY);
  4389     if (ldX.isNegative = ldY.isNegative) then sdY := -sdY;
  4551     if (ldX.isNegative = ldY.isNegative) then
       
  4552         sdY := -sdY;
  4390 
  4553 
  4391     // initial angle depends on current GameTicks
  4554     // initial angle depends on current GameTicks
  4392     t := GameTicks mod 4096;
  4555     t := GameTicks mod 4096;
  4393 
  4556 
  4394 
  4557 
  4415         x := hwRound(Gear^.X);
  4578         x := hwRound(Gear^.X);
  4416         y := hwRound(Gear^.Y);
  4579         y := hwRound(Gear^.Y);
  4417 
  4580 
  4418         // if borders are on, stop outside land array
  4581         // if borders are on, stop outside land array
  4419         if hasBorder and (((x and LAND_WIDTH_MASK) <> 0) or ((y and LAND_HEIGHT_MASK) <> 0)) then
  4582         if hasBorder and (((x and LAND_WIDTH_MASK) <> 0) or ((y and LAND_HEIGHT_MASK) <> 0)) then
  4420         begin
  4583             begin
  4421             Gear^.Damage := 0;
  4584             Gear^.Damage := 0;
  4422             Gear^.Health := 0;
  4585             Gear^.Health := 0;
  4423         end
  4586             end
  4424         else
  4587         else
  4425         begin
  4588             begin
  4426             if (rY <= cWaterLine) or (y <= cWaterLine) then
  4589             if (rY <= cWaterLine) or (y <= cWaterLine) then
  4427             begin
  4590                 begin
  4428                 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0)
  4591                 if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0)
  4429                    and (Land[y, x] <> 0) then
  4592                     and (Land[y, x] <> 0) then
  4430                 begin
  4593                         begin
  4431                     if justCollided then
  4594                             if justCollided then
  4432                     begin
  4595                                 begin
  4433                         Gear^.Damage := 0;
  4596                                 Gear^.Damage := 0;
  4434                         Gear^.Health := 0;
  4597                                 Gear^.Health := 0;
  4435                     end
  4598                                 end
  4436                     else
  4599                             else
  4437                     begin
  4600                                 begin
  4438                         inc(Gear^.Damage,3);
  4601                                 inc(Gear^.Damage,3);
  4439                         justCollided := true;
  4602                                 justCollided := true;
  4440                     end;
  4603                                 end;
  4441                 end
  4604                         end
  4442                 else
  4605                 else
  4443                     justCollided := false;
  4606                     justCollided := false;
  4444 
  4607 
  4445                 // kick nearby hogs, dig tunnel and add some fire
  4608                 // kick nearby hogs, dig tunnel and add some fire
  4446                 // if at least 5 collisions occured
  4609                 // if at least 5 collisions occured
  4447                 if Gear^.Damage > 0 then
  4610                 if Gear^.Damage > 0 then
  4448                 begin
  4611                     begin
  4449                     DrawExplosion(rX,rY,Gear^.Radius);
  4612                     DrawExplosion(rX,rY,Gear^.Radius);
  4450 
  4613 
  4451                     // kick nearby hogs
  4614                     // kick nearby hogs
  4452                     AmmoShove(Gear, 35, 50);
  4615                     AmmoShove(Gear, 35, 50);
  4453 
  4616 
  4456 
  4619 
  4457                     // add some fire to the tunnel
  4620                     // add some fire to the tunnel
  4458                     if getRandom(6) = 0 then
  4621                     if getRandom(6) = 0 then
  4459                         AddGear(x - Gear^.Radius + LongInt(getRandom(2 * Gear^.Radius)), y -
  4622                         AddGear(x - Gear^.Radius + LongInt(getRandom(2 * Gear^.Radius)), y -
  4460                         getRandom(Gear^.Radius + 1), gtFlame, gsttmpFlag, _0, _0, 0);
  4623                         getRandom(Gear^.Radius + 1), gtFlame, gsttmpFlag, _0, _0, 0);
  4461                 end;
  4624                     end;
  4462 
  4625 
  4463                 if getRandom(100) = 0 then
  4626                 if getRandom(100) = 0 then
  4464                     AddVisualGear(x, y, vgtSmokeTrace); 
  4627                     AddVisualGear(x, y, vgtSmokeTrace); 
       
  4628                 end
       
  4629                 else dec(Gear^.Health, 5); // if underwater get additional damage
       
  4630             end;
       
  4631 
       
  4632         dec(Gear^.Health);
       
  4633 
       
  4634         // decrease bullet size towards the end
       
  4635         if (Gear^.Radius > 4) then
       
  4636             begin
       
  4637             if (Gear^.Health <= (initHealth div 3)) then
       
  4638                 dec(Gear^.Radius)
  4465             end
  4639             end
  4466             else dec(Gear^.Health, 5); // if underwater get additional damage
  4640         else if (Gear^.Radius > 3) then
  4467         end;
  4641             begin
  4468 
  4642             if (Gear^.Health <= (initHealth div 4)) then
  4469         dec(Gear^.Health);
  4643                 dec(Gear^.Radius)
  4470 
  4644             end
  4471         // decrease bullet size towards the end
       
  4472         if (Gear^.Radius > 4) then begin
       
  4473             if (Gear^.Health <= (initHealth div 3)) then dec(Gear^.Radius) end
       
  4474         else if (Gear^.Radius > 3) then begin
       
  4475             if (Gear^.Health <= (initHealth div 4)) then dec(Gear^.Radius) end
       
  4476         else if (Gear^.Radius > 2) then begin
  4645         else if (Gear^.Radius > 2) then begin
  4477             if (Gear^.Health <= (initHealth div 5)) then dec(Gear^.Radius) end
  4646             if (Gear^.Health <= (initHealth div 5)) then
  4478         else if (Gear^.Radius > 1) then begin
  4647                 dec(Gear^.Radius)
  4479             if (Gear^.Health <= (initHealth div 6)) then dec(Gear^.Radius) end;
  4648             end
       
  4649         else if (Gear^.Radius > 1) then
       
  4650             begin
       
  4651             if (Gear^.Health <= (initHealth div 6)) then
       
  4652                 dec(Gear^.Radius)
       
  4653             end;
  4480 
  4654 
  4481     until (Gear^.Health <= 0);
  4655     until (Gear^.Health <= 0);
  4482 
  4656 
  4483     DeleteGear(Gear);
  4657     DeleteGear(Gear);
  4484     AfterAttack;
  4658     AfterAttack;
  4519     
  4693     
  4520     if (GameTicks and $FF) = 0 then
  4694     if (GameTicks and $FF) = 0 then
  4521         begin
  4695         begin
  4522         if (HHGear^.Message and gmRight) <> 0 then
  4696         if (HHGear^.Message and gmRight) <> 0 then
  4523             begin
  4697             begin
  4524             if HHGear^.dX.isNegative and (Gear^.Tag < 20) then inc(Gear^.Tag)
  4698             if HHGear^.dX.isNegative and (Gear^.Tag < 20) then
  4525             else if Gear^.Tag > 5 then dec(Gear^.Tag);
  4699                 inc(Gear^.Tag)
       
  4700             else if Gear^.Tag > 5 then
       
  4701                 dec(Gear^.Tag);
  4526             end
  4702             end
  4527         else if (HHGear^.Message and gmLeft) <> 0 then
  4703         else if (HHGear^.Message and gmLeft) <> 0 then
  4528             begin
  4704             begin
  4529             if HHGear^.dX.isNegative and (Gear^.Tag > 5) then dec(Gear^.Tag)
  4705             if HHGear^.dX.isNegative and (Gear^.Tag > 5) then
  4530             else if Gear^.Tag < 20 then inc(Gear^.Tag);
  4706                 dec(Gear^.Tag)
       
  4707             else if Gear^.Tag < 20 then 
       
  4708                 inc(Gear^.Tag);
  4531             end
  4709             end
  4532         end;
  4710         end;
  4533     
  4711     
  4534     dec(Gear^.Timer);
  4712     dec(Gear^.Timer);
  4535     if Gear^.Timer = 0 then
  4713     if Gear^.Timer = 0 then
  4596     
  4774     
  4597     if (GameTicks and $FF) = 0 then
  4775     if (GameTicks and $FF) = 0 then
  4598         begin
  4776         begin
  4599         if (HHGear^.Message and gmRight) <> 0 then
  4777         if (HHGear^.Message and gmRight) <> 0 then
  4600             begin
  4778             begin
  4601             if HHGear^.dX.isNegative and (Gear^.Tag < 20) then inc(Gear^.Tag)
  4779             if HHGear^.dX.isNegative and (Gear^.Tag < 20) then
  4602             else if Gear^.Tag > 5 then dec(Gear^.Tag);
  4780                 inc(Gear^.Tag)
       
  4781             else if Gear^.Tag > 5 then
       
  4782                 dec(Gear^.Tag);
  4603             end
  4783             end
  4604         else if (HHGear^.Message and gmLeft) <> 0 then
  4784         else if (HHGear^.Message and gmLeft) <> 0 then
  4605             begin
  4785             begin
  4606             if HHGear^.dX.isNegative and (Gear^.Tag > 5) then dec(Gear^.Tag)
  4786             if HHGear^.dX.isNegative and (Gear^.Tag > 5) then
  4607             else if Gear^.Tag < 20 then inc(Gear^.Tag);
  4787                 dec(Gear^.Tag)
       
  4788             else if Gear^.Tag < 20 then
       
  4789                 inc(Gear^.Tag);
  4608             end
  4790             end
  4609         end;
  4791         end;
  4610     
  4792     
  4611     dec(Gear^.Timer);
  4793     dec(Gear^.Timer);
  4612     if Gear^.Timer = 0 then
  4794     if Gear^.Timer = 0 then
  4655 
  4837 
  4656 ////////////////////////////////////////////////////////////////////////////////
  4838 ////////////////////////////////////////////////////////////////////////////////
  4657 procedure doStepPoisonCloud(Gear: PGear);
  4839 procedure doStepPoisonCloud(Gear: PGear);
  4658 begin
  4840 begin
  4659     if Gear^.Timer = 0 then
  4841     if Gear^.Timer = 0 then
  4660     begin
  4842         begin
  4661         DeleteGear(Gear);
  4843         DeleteGear(Gear);
  4662         exit
  4844         exit
  4663     end;
  4845         end;
  4664     dec(Gear^.Timer);
  4846     dec(Gear^.Timer);
  4665     Gear^.X:= Gear^.X + Gear^.dX;
  4847     Gear^.X:= Gear^.X + Gear^.dX;
  4666     Gear^.Y:= Gear^.Y + Gear^.dY;
  4848     Gear^.Y:= Gear^.Y + Gear^.dY;
  4667     Gear^.dX := Gear^.dX + cWindSpeed / 4;
  4849     Gear^.dX := Gear^.dX + cWindSpeed / 4;
  4668     Gear^.dY := Gear^.dY + cGravity / 100;
  4850     Gear^.dY := Gear^.dY + cGravity / 100;
  4693     tmp:= t^.ar[i];
  4875     tmp:= t^.ar[i];
  4694     if (tmp^.State and gstNoDamage) = 0 then
  4876     if (tmp^.State and gstNoDamage) = 0 then
  4695         if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then
  4877         if (tmp^.Kind = gtHedgehog) or (tmp^.Kind = gtMine) or (tmp^.Kind = gtExplosives) then
  4696             begin
  4878             begin
  4697             //tmp^.State:= tmp^.State or gstFlatened;
  4879             //tmp^.State:= tmp^.State or gstFlatened;
  4698             if not tmp^.Invulnerable then ApplyDamage(tmp, CurrentHedgehog, tmp^.Health div 3, dsUnknown);
  4880             if not tmp^.Invulnerable then
       
  4881                 ApplyDamage(tmp, CurrentHedgehog, tmp^.Health div 3, dsUnknown);
  4699             //DrawTunnel(tmp^.X, tmp^.Y - _1, _0, _0_5, cHHRadius * 6, cHHRadius * 3);
  4882             //DrawTunnel(tmp^.X, tmp^.Y - _1, _0, _0_5, cHHRadius * 6, cHHRadius * 3);
  4700             tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0);
  4883             tmp2:= AddGear(hwRound(tmp^.X), hwRound(tmp^.Y), gtHammerHit, 0, _0, _0, 0);
  4701             tmp2^.IntersectGear:= tmp;
  4884             tmp2^.IntersectGear:= tmp;
  4702             SetAllToActive
  4885             SetAllToActive
  4703             end
  4886             end
  4754         end
  4937         end
  4755     else
  4938     else
  4756         begin
  4939         begin
  4757         Gear^.dY := Gear^.dY + cGravity;
  4940         Gear^.dY := Gear^.dY + cGravity;
  4758         Gear^.Y := Gear^.Y + Gear^.dY;
  4941         Gear^.Y := Gear^.Y + Gear^.dY;
  4759         if hwRound(Gear^.Y) > cWaterLine then Gear^.Timer := 1
  4942         if hwRound(Gear^.Y) > cWaterLine then
       
  4943             Gear^.Timer := 1
  4760         end;
  4944         end;
  4761 
  4945 
  4762     Gear^.X := Gear^.X + HitGear^.dX;
  4946     Gear^.X := Gear^.X + HitGear^.dX;
  4763     HitGear^.X := Gear^.X;
  4947     HitGear^.X := Gear^.X;
  4764     SetLittle(HitGear^.dY);
  4948     SetLittle(HitGear^.dY);
  4774     i := 0;
  4958     i := 0;
  4775     HHGear := Gear^.Hedgehog^.Gear;
  4959     HHGear := Gear^.Hedgehog^.Gear;
  4776 
  4960 
  4777     y := hwRound(Gear^.Y) - cHHRadius * 2;
  4961     y := hwRound(Gear^.Y) - cHHRadius * 2;
  4778     while y < hwRound(Gear^.Y) do
  4962     while y < hwRound(Gear^.Y) do
  4779     begin
  4963         begin
  4780         ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
  4964         ar[i].Left := hwRound(Gear^.X) - Gear^.Radius - LongInt(GetRandom(2));
  4781         ar[i].Right := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
  4965         ar[i].Right := hwRound(Gear^.X) + Gear^.Radius + LongInt(GetRandom(2));
  4782         inc(y, 2);
  4966         inc(y, 2);
  4783         inc(i)
  4967         inc(i)
  4784     end;
  4968         end;
  4785 
  4969 
  4786     DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius * 2, 2, Pred(i));
  4970     DrawHLinesExplosions(@ar, 3, hwRound(Gear^.Y) - cHHRadius * 2, 2, Pred(i));
  4787     Gear^.dY := HHGear^.dY;
  4971     Gear^.dY := HHGear^.dY;
  4788     DeleteCI(HHGear);
  4972     DeleteCI(HHGear);
  4789 
  4973 
  4812     (*DrawCircle(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, 1.5, 0, 0, $FF,
  4996     (*DrawCircle(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Radius, 1.5, 0, 0, $FF,
  4813             $FF);*)
  4997             $FF);*)
  4814 
  4998 
  4815     if ((Gear^.Message and gmUp) <> 0) then
  4999     if ((Gear^.Message and gmUp) <> 0) then
  4816         begin
  5000         begin
  4817         if (GameTicks and $F) <> 0 then exit;
  5001         if (GameTicks and $F) <> 0 then
       
  5002         exit;
  4818         end 
  5003         end 
  4819     else if (GameTicks and $1FF) <> 0 then exit;
  5004     else if (GameTicks and $1FF) <> 0 then
       
  5005         exit;
  4820 
  5006 
  4821     if Gear^.Power < 45 then
  5007     if Gear^.Power < 45 then
  4822         begin
  5008         begin
  4823         inc(Gear^.Power);
  5009         inc(Gear^.Power);
  4824         if TestCollisionYwithGear(hh^.Gear, -1) = 0 then hh^.Gear^.Y := hh^.Gear^.Y - _1;
  5010         if TestCollisionYwithGear(hh^.Gear, -1) = 0 then
       
  5011             hh^.Gear^.Y := hh^.Gear^.Y - _1;
  4825         end;
  5012         end;
  4826 
  5013 
  4827     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
  5014     graves := GearsNear(Gear^.X, Gear^.Y, gtGrave, Gear^.Radius);
  4828 
  5015 
  4829     if Length(graves) = 0 then
  5016     if Length(graves) = 0 then
  4854         begin
  5041         begin
  4855         // now really resurrect the hogs with the hp saved in the graves
  5042         // now really resurrect the hogs with the hp saved in the graves
  4856         for i:= 0 to High(graves) do
  5043         for i:= 0 to High(graves) do
  4857             if graves[i]^.Health > 0 then
  5044             if graves[i]^.Health > 0 then
  4858                 begin
  5045                 begin
  4859                 resgear := AddGear(hwRound(graves[i]^.X), hwRound(graves[i]^.Y),
  5046                 resgear := AddGear(hwRound(graves[i]^.X), hwRound(graves[i]^.Y), gtHedgehog, gstWait, _0, _0, 0);
  4860                         gtHedgehog, gstWait, _0, _0, 0);
       
  4861                 resgear^.Hedgehog := graves[i]^.Hedgehog;
  5047                 resgear^.Hedgehog := graves[i]^.Hedgehog;
  4862                 resgear^.Health := graves[i]^.Health;
  5048                 resgear^.Health := graves[i]^.Health;
  4863                 PHedgehog(graves[i]^.Hedgehog)^.Gear := resgear;
  5049                 PHedgehog(graves[i]^.Hedgehog)^.Gear := resgear;
  4864                 DeleteGear(graves[i]);
  5050                 DeleteGear(graves[i]);
  4865                 RenderHealth(resgear^.Hedgehog^);
  5051                 RenderHealth(resgear^.Hedgehog^);
  4866                 RecountTeamHealth(resgear^.Hedgehog^.Team);
  5052                 RecountTeamHealth(resgear^.Hedgehog^.Team);
  4867                 resgear^.Hedgehog^.Effects[heResurrected]:= true;
  5053                 resgear^.Hedgehog^.Effects[heResurrected]:= true;
  4868                 // only make hat-less hedgehogs look like zombies, preserve existing hats
  5054                 // only make hat-less hedgehogs look like zombies, preserve existing hats
       
  5055                 
  4869                 if resgear^.Hedgehog^.Hat = 'NoHat' then
  5056                 if resgear^.Hedgehog^.Hat = 'NoHat' then
  4870                     LoadHedgehogHat(resgear, 'Reserved/Zombie');
  5057                     LoadHedgehogHat(resgear, 'Reserved/Zombie');
  4871                 end;
  5058                 end;
  4872 
  5059 
  4873         hh^.Gear^.dY := _0;
  5060         hh^.Gear^.dY := _0;
  4929         end;
  5116         end;
  4930         DeleteGear(Gear);
  5117         DeleteGear(Gear);
  4931         exit
  5118         exit
  4932     end;
  5119     end;
  4933     if (Gear^.Timer = 0) then
  5120     if (Gear^.Timer = 0) then
  4934     begin
  5121         begin
  4935         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 10, Gear^.Hedgehog, EXPLAutoSound);
  5122         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 10, Gear^.Hedgehog, EXPLAutoSound);
  4936         for i:= -19 to 19 do
  5123         for i:= -19 to 19 do
  4937            FollowGear := AddGear(hwRound(Gear^.X) + i div 3, hwRound(Gear^.Y), gtFlame, 0, _0_001 * i, _0, 0);
  5124            FollowGear := AddGear(hwRound(Gear^.X) + i div 3, hwRound(Gear^.Y), gtFlame, 0, _0_001 * i, _0, 0);
  4938         DeleteGear(Gear);
  5125         DeleteGear(Gear);
  4939         exit
  5126         exit
  4940     end;
  5127         end;
  4941     if (GameTicks and $3F) = 0 then
  5128     if (GameTicks and $3F) = 0 then
  4942         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  5129         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace);
  4943     dec(Gear^.Timer)
  5130     dec(Gear^.Timer)
  4944 end;
  5131 end;
  4945 
  5132 
  4965         
  5152         
  4966     if Gear^.Pos = 1 then
  5153     if Gear^.Pos = 1 then
  4967         begin
  5154         begin
  4968         AddGearCI(Gear);
  5155         AddGearCI(Gear);
  4969         AfterAttack;
  5156         AfterAttack;
  4970         if Gear = CurAmmoGear then CurAmmoGear:= nil;
  5157         if Gear = CurAmmoGear then
  4971         if HH^.Gear <> nil then HideHog(HH);
  5158             CurAmmoGear:= nil;
       
  5159         if HH^.Gear <> nil then
       
  5160             HideHog(HH);
  4972         Gear^.Pos:= 2
  5161         Gear^.Pos:= 2
  4973         end;
  5162         end;
  4974         
  5163         
  4975     if Gear^.Pos = 2 then
  5164     if Gear^.Pos = 2 then
  4976         begin
  5165         begin
  4982                 Gear^.Y:= Gear^.Y - _0_5;
  5171                 Gear^.Y:= Gear^.Y - _0_5;
  4983                 AddGearCI(Gear);
  5172                 AddGearCI(Gear);
  4984                 end;
  5173                 end;
  4985             inc(Gear^.Timer);
  5174             inc(Gear^.Timer);
  4986             end;
  5175             end;
  4987         if Gear^.Tag <= TotalRounds then Gear^.Pos:= 3;
  5176         if Gear^.Tag <= TotalRounds then
       
  5177             Gear^.Pos:= 3;
  4988         end;
  5178         end;
  4989         
  5179         
  4990     if Gear^.Pos = 3 then
  5180     if Gear^.Pos = 3 then
  4991         if Gear^.Timer < 1000 then
  5181         if Gear^.Timer < 1000 then
  4992             begin
  5182             begin
  4998                 end;
  5188                 end;
  4999             inc(Gear^.Timer);
  5189             inc(Gear^.Timer);
  5000             end
  5190             end
  5001         else
  5191         else
  5002             begin
  5192             begin
  5003             if HH^.GearHidden <> nil then RestoreHog(HH);
  5193             if HH^.GearHidden <> nil then
       
  5194                 RestoreHog(HH);
  5004             Gear^.Pos:= 4;
  5195             Gear^.Pos:= 4;
  5005             end;
  5196             end;
  5006         
  5197         
  5007     if Gear^.Pos = 4 then
  5198     if Gear^.Pos = 4 then
  5008         if ((GameTicks mod 1000) = 0) and ((GameFlags and gfInvulnerable) = 0) then
  5199         if ((GameTicks mod 1000) = 0) and ((GameFlags and gfInvulnerable) = 0) then
  5016                 end;
  5207                 end;
  5017             end;
  5208             end;
  5018         
  5209         
  5019     if Gear^.Health <= 0 then
  5210     if Gear^.Health <= 0 then
  5020         begin
  5211         begin
  5021         if HH^.GearHidden <> nil then RestoreHog(HH);
  5212         if HH^.GearHidden <> nil then
       
  5213             RestoreHog(HH);
  5022         
  5214         
  5023         x := hwRound(Gear^.X);
  5215         x := hwRound(Gear^.X);
  5024         y := hwRound(Gear^.Y);
  5216         y := hwRound(Gear^.Y);
  5025 
  5217 
  5026         DeleteCI(Gear);
  5218         DeleteCI(Gear);
  5077 
  5269 
  5078 if (Gear^.Pos = 1) and (GameTicks and $1F = 0) and (Gear^.Power < 255) then
  5270 if (Gear^.Pos = 1) and (GameTicks and $1F = 0) and (Gear^.Power < 255) then
  5079     begin
  5271     begin
  5080     inc(Gear^.Power);
  5272     inc(Gear^.Power);
  5081     if (Gear^.Power = 172) and (HH^.Gear <> nil) and 
  5273     if (Gear^.Power = 172) and (HH^.Gear <> nil) and 
  5082        (HH^.Gear^.Damage = 0) and (HH^.Gear^.Health > 0) and
  5274         (HH^.Gear^.Damage = 0) and (HH^.Gear^.Health > 0) and
  5083        ((HH^.Gear^.State and (gstMoving or gstHHDeath or gstHHGone)) = 0) then
  5275         ((HH^.Gear^.State and (gstMoving or gstHHDeath or gstHHGone)) = 0) then
  5084         with HH^.Gear^ do
  5276             with HH^.Gear^ do
  5085             begin
  5277                 begin
  5086             State:= State or gstAnimation;
  5278                 State:= State or gstAnimation;
  5087             Tag:= 2;
  5279                 Tag:= 2;
  5088             Timer:= 0;
  5280                 Timer:= 0;
  5089             Pos:= 0
  5281                 Pos:= 0
  5090             end
  5282                 end
  5091     end;
  5283     end;
  5092 if (Gear^.Pos = 3) and (GameTicks and $1F = 0) and (Gear^.Power > 0) then dec(Gear^.Power);
  5284 if (Gear^.Pos = 3) and (GameTicks and $1F = 0) and (Gear^.Power > 0) then
  5093 if (Gear^.Pos = 1) and (Gear^.Power = 255) and ((GameTicks mod 2000) = 1000) then Gear^.Pos:= 2;
  5285     dec(Gear^.Power);
       
  5286 if (Gear^.Pos = 1) and (Gear^.Power = 255) and ((GameTicks mod 2000) = 1000) then
       
  5287     Gear^.Pos:= 2;
  5094 if (Gear^.Pos = 3) and (Gear^.Power = 0) then
  5288 if (Gear^.Pos = 3) and (Gear^.Power = 0) then
  5095     begin
  5289     begin
  5096     StopSound(Gear^.SoundChannel);
  5290     StopSound(Gear^.SoundChannel);
  5097     if HH^.GearHidden = nil then
  5291     if HH^.GearHidden = nil then
  5098         begin
  5292         begin
  5107 if (Gear^.Pos = 4) then
  5301 if (Gear^.Pos = 4) then
  5108     begin
  5302     begin
  5109     cnt:= 0;
  5303     cnt:= 0;
  5110     for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
  5304     for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
  5111         for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do
  5305         for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do
  5112             if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil) and
  5306             if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil)
  5113                ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0) and
  5307             and ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0)
  5114                (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health >
  5308             and (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health > HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then
  5115                 HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then inc(cnt);
  5309                 inc(cnt);
       
  5310                 
  5116     if (cnt = 0) or SuddenDeathDmg or (Gear^.Timer = 0) then
  5311     if (cnt = 0) or SuddenDeathDmg or (Gear^.Timer = 0) then
  5117         begin
  5312         begin
  5118         Gear^.SoundChannel := LoopSound(sndTardis);
  5313         Gear^.SoundChannel := LoopSound(sndTardis);
  5119         Gear^.Pos:= 1;
  5314         Gear^.Pos:= 1;
  5120         Gear^.Power:= 0;
  5315         Gear^.Power:= 0;
  5121         Gear^.Timer:= 0;
  5316         Gear^.Timer:= 0;
  5122         if HH^.GearHidden <> nil then FindPlace(HH^.GearHidden, false, 0, LAND_WIDTH,true);
  5317         
       
  5318         if HH^.GearHidden <> nil then
       
  5319             FindPlace(HH^.GearHidden, false, 0, LAND_WIDTH,true);
       
  5320             
  5123         if HH^.GearHidden <> nil then
  5321         if HH^.GearHidden <> nil then
  5124             begin
  5322             begin
  5125             Gear^.X:= HH^.GearHidden^.X;
  5323             Gear^.X:= HH^.GearHidden^.X;
  5126             Gear^.Y:= HH^.GearHidden^.Y;
  5324             Gear^.Y:= HH^.GearHidden^.Y;
  5127             //HH^.Gear:=HH^.GearHidden;
  5325             //HH^.Gear:=HH^.GearHidden;
  5158         exit
  5356         exit
  5159         end;
  5357         end;
  5160     cnt:= 0;
  5358     cnt:= 0;
  5161     for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
  5359     for j:= 0 to Pred(HH^.Team^.Clan^.TeamsNumber) do
  5162         for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do
  5360         for i:= 0 to Pred(HH^.Team^.Clan^.Teams[j]^.HedgehogsNumber) do
  5163             if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil) and
  5361             if (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear <> nil)
  5164                ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0) and
  5362             and ((HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.State and gstDrowning) = 0)
  5165                (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health >
  5363             and (HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Health > HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then
  5166                 HH^.Team^.Clan^.Teams[j]^.Hedgehogs[i].Gear^.Damage) then inc(cnt);
  5364                 inc(cnt);
  5167     if cnt < 2 then
  5365     if cnt < 2 then
  5168         begin
  5366         begin
  5169         if HH^.Gear <> nil then
  5367         if HH^.Gear <> nil then
  5170             begin
  5368             begin
  5171             HH^.Gear^.Message := HH^.Gear^.Message and (not gmAttack);
  5369             HH^.Gear^.Message := HH^.Gear^.Message and (not gmAttack);