hedgewars/GSHandlers.inc
branchwebgl
changeset 8105 d088be5ecdcb
parent 8096 453917e94e55
child 8330 aaefa587e277
equal deleted inserted replaced
8102:20ef5bf0dc7f 8105:d088be5ecdcb
   149     begin
   149     begin
   150     AllInactive := false;
   150     AllInactive := false;
   151     Gear^.Y := Gear^.Y + cDrownSpeed;
   151     Gear^.Y := Gear^.Y + cDrownSpeed;
   152     Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
   152     Gear^.X := Gear^.X + Gear^.dX * cDrownSpeed;
   153     // Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
   153     // Create some bubbles (0.5% might be better but causes too few bubbles sometimes)
   154     if ((not SuddenDeathDmg and (WaterOpacity < $FF))
   154     if (((not SuddenDeathDmg) and (WaterOpacity < $FF))
   155     or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
   155     or (SuddenDeathDmg and (SDWaterOpacity < $FF))) and ((GameTicks and $1F) = 0) then
   156         if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
   156         if (Gear^.Kind = gtHedgehog) and (Random(4) = 0) then
   157             AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble)
   157             AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble)
   158     else if Random(12) = 0 then
   158     else if Random(12) = 0 then
   159              AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble);
   159              AddVisualGear(hwRound(Gear^.X) - Gear^.Radius, hwRound(Gear^.Y) - Gear^.Radius, vgtBubble);
   160     if (not SuddenDeathDmg and (WaterOpacity > $FE))
   160     if ((not SuddenDeathDmg) and (WaterOpacity > $FE))
   161     or (SuddenDeathDmg and (SDWaterOpacity > $FE))
   161     or (SuddenDeathDmg and (SDWaterOpacity > $FE))
   162     or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
   162     or (hwRound(Gear^.Y) > Gear^.Radius + cWaterLine + cVisibleWater) then
   163         DeleteGear(Gear);
   163         DeleteGear(Gear);
   164     end;
   164     end;
   165 
   165 
   258     or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)) then
   258     or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)) then
   259         begin
   259         begin
   260         Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
   260         Gear^.dX := tdY*Gear^.Elasticity*Gear^.Friction;
   261         Gear^.dY := tdX*Gear^.Elasticity;
   261         Gear^.dY := tdX*Gear^.Elasticity;
   262         //*Gear^.Friction;
   262         //*Gear^.Friction;
   263         Gear^.dY.isNegative := not tdY.isNegative;
   263         Gear^.dY.isNegative := (not tdY.isNegative);
   264         isFalling := false;
   264         isFalling := false;
   265         Gear^.AdvBounce := 10;
   265         Gear^.AdvBounce := 10;
   266         end;
   266         end;
   267 
   267 
   268     if Gear^.AdvBounce > 1 then
   268     if Gear^.AdvBounce > 1 then
   533     doStepFallingGear(Gear);
   533     doStepFallingGear(Gear);
   534     CalcRotationDirAngle(Gear);
   534     CalcRotationDirAngle(Gear);
   535     if (Gear^.State and gstCollision) <> 0 then
   535     if (Gear^.State and gstCollision) <> 0 then
   536         begin
   536         begin
   537         kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
   537         kick:= hwRound((hwAbs(Gear^.dX)+hwAbs(Gear^.dY)) * _20);
   538         Gear^.dY.isNegative:= not Gear^.dY.isNegative;
   538         Gear^.dY.isNegative:= (not Gear^.dY.isNegative);
   539         Gear^.dX.isNegative:= not Gear^.dX.isNegative;
   539         Gear^.dX.isNegative:= (not Gear^.dX.isNegative);
   540         AmmoShove(Gear, 0, kick);
   540         AmmoShove(Gear, 0, kick);
   541         for i:= 15 + kick div 10 downto 0 do
   541         for i:= 15 + kick div 10 downto 0 do
   542             begin
   542             begin
   543             particle := AddVisualGear(hwRound(Gear^.X) + Random(25), hwRound(Gear^.Y) + Random(25), vgtDust);
   543             particle := AddVisualGear(hwRound(Gear^.X) + Random(25), hwRound(Gear^.Y) + Random(25), vgtDust);
   544             if particle <> nil then
   544             if particle <> nil then
   740 
   740 
   741     if Gear^.dY.isNegative then
   741     if Gear^.dY.isNegative then
   742         if TestCollisionY(Gear, -1) then
   742         if TestCollisionY(Gear, -1) then
   743             Gear^.dY := _0;
   743             Gear^.dY := _0;
   744 
   744 
   745     if not Gear^.dY.isNegative then
   745     if (not Gear^.dY.isNegative) then
   746         if TestCollisionY(Gear, 1) then
   746         if TestCollisionY(Gear, 1) then
   747         begin
   747         begin
   748             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
   748             Gear^.dY := - Gear^.dY * Gear^.Elasticity;
   749             if Gear^.dY > - _1div1024 then
   749             if Gear^.dY > - _1div1024 then
   750             begin
   750             begin
  1043         begin
  1043         begin
  1044         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
  1044         DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1);
  1045         dec(Gear^.Health, Gear^.Damage);
  1045         dec(Gear^.Health, Gear^.Damage);
  1046         Gear^.Damage := 0
  1046         Gear^.Damage := 0
  1047         end;
  1047         end;
  1048     if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and ((not SuddenDeathDmg and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then
  1048     if ((Gear^.State and gstDrowning) <> 0) and (Gear^.Damage < Gear^.Health) and (((not SuddenDeathDmg) and (WaterOpacity < $FF)) or (SuddenDeathDmg and (SDWaterOpacity < $FF))) then
  1049         begin
  1049         begin
  1050         for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do
  1050         for i:=(Gear^.Health - Gear^.Damage) * 4 downto 0 do
  1051             begin
  1051             begin
  1052             if Random(6) = 0 then
  1052             if Random(6) = 0 then
  1053                 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble);
  1053                 AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtBubble);
  1423         end
  1423         end
  1424     else if (GameTicks and $3F) = 25 then
  1424     else if (GameTicks and $3F) = 25 then
  1425         doStepFallingGear(Gear);
  1425         doStepFallingGear(Gear);
  1426     if (Gear^.Health = 0) then
  1426     if (Gear^.Health = 0) then
  1427         begin
  1427         begin
  1428         if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1428         if (not Gear^.dY.isNegative) and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1429             inc(Gear^.Damage, hwRound(Gear^.dY * _70))
  1429             inc(Gear^.Damage, hwRound(Gear^.dY * _70))
  1430         else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1430         else if (not Gear^.dX.isNegative) and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1431             inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  1431             inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  1432         else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1432         else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1433             inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  1433             inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  1434         else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
  1434         else if Gear^.dX.isNegative and (Gear^.dX < -_0_2) and TestCollisionXwithGear(Gear, -1) then
  1435             inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
  1435             inc(Gear^.Damage, hwRound(Gear^.dX * -_70));
  1583     if ((Gear^.dX.QWordValue <> 0)
  1583     if ((Gear^.dX.QWordValue <> 0)
  1584     or (Gear^.dY.QWordValue <> 0))  then
  1584     or (Gear^.dY.QWordValue <> 0))  then
  1585         begin
  1585         begin
  1586         DeleteCI(Gear);
  1586         DeleteCI(Gear);
  1587         AllInactive := false;
  1587         AllInactive := false;
  1588         if not Gear^.dY.isNegative and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1588         if (not Gear^.dY.isNegative) and (Gear^.dY > _0_2) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1589             begin
  1589             begin
  1590             Gear^.State := Gear^.State or gsttmpFlag;
  1590             Gear^.State := Gear^.State or gsttmpFlag;
  1591             inc(Gear^.Damage, hwRound(Gear^.dY * _70));
  1591             inc(Gear^.Damage, hwRound(Gear^.dY * _70));
  1592             for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
  1592             for i:= min(12, hwRound(Gear^.dY*_10)) downto 0 do
  1593                 begin
  1593                 begin
  1594                 particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,vgtDust);
  1594                 particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12,vgtDust);
  1595                 if particle <> nil then
  1595                 if particle <> nil then
  1596                     particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
  1596                     particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480)
  1597                 end
  1597                 end
  1598             end
  1598             end
  1599         else if not Gear^.dX.isNegative and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1599         else if (not Gear^.dX.isNegative) and (Gear^.dX > _0_2) and TestCollisionXwithGear(Gear, 1) then
  1600                 inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  1600                 inc(Gear^.Damage, hwRound(Gear^.dX * _70))
  1601                 
  1601                 
  1602         else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1602         else if Gear^.dY.isNegative and (Gear^.dY < -_0_2) and (TestCollisionYwithGear(Gear, -1) <> 0) then
  1603                 inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  1603                 inc(Gear^.Damage, hwRound(Gear^.dY * -_70))
  1604                 
  1604                 
  1629                 Gear^.dX:= _0_08;
  1629                 Gear^.dX:= _0_08;
  1630             end;
  1630             end;
  1631     if Gear^.dX.QWordValue = 0 then AddGearCI(Gear)
  1631     if Gear^.dX.QWordValue = 0 then AddGearCI(Gear)
  1632     end; *)
  1632     end; *)
  1633 
  1633 
  1634     if not Gear^.dY.isNegative and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1634     if (not Gear^.dY.isNegative) and (Gear^.dY < _0_001) and (TestCollisionYwithGear(Gear, 1) <> 0) then
  1635         Gear^.dY := _0;
  1635         Gear^.dY := _0;
  1636     if hwAbs(Gear^.dX) < _0_001 then
  1636     if hwAbs(Gear^.dX) < _0_001 then
  1637         Gear^.dX := _0;
  1637         Gear^.dX := _0;
  1638 
  1638 
  1639     if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
  1639     if (Gear^.Health > 0) and ((Gear^.Health * 100 div cBarrelHealth) < random(90)) and ((GameTicks and $FF) = 0) then
  1889     sticky: Boolean;
  1889     sticky: Boolean;
  1890     vgt: PVisualGear;
  1890     vgt: PVisualGear;
  1891     tdX,tdY: HWFloat;
  1891     tdX,tdY: HWFloat;
  1892 begin
  1892 begin
  1893     sticky:= (Gear^.State and gsttmpFlag) <> 0;
  1893     sticky:= (Gear^.State and gsttmpFlag) <> 0;
  1894     if not sticky then AllInactive := false;
  1894     if (not sticky) then AllInactive := false;
  1895 
  1895 
  1896     if TestCollisionYwithGear(Gear, 1) = 0 then
  1896     if TestCollisionYwithGear(Gear, 1) = 0 then
  1897         begin
  1897         begin
  1898         AllInactive := false;
  1898         AllInactive := false;
  1899 
  1899 
  1956         else
  1956         else
  1957             begin
  1957             begin
  1958             gX := hwRound(Gear^.X);
  1958             gX := hwRound(Gear^.X);
  1959             gY := hwRound(Gear^.Y);
  1959             gY := hwRound(Gear^.Y);
  1960             // Standard fire
  1960             // Standard fire
  1961             if not sticky then
  1961             if (not sticky) then
  1962                 begin
  1962                 begin
  1963                 if ((GameTicks and $1) = 0) then
  1963                 if ((GameTicks and $1) = 0) then
  1964                     begin
  1964                     begin
  1965                     Gear^.Radius := 7;
  1965                     Gear^.Radius := 7;
  1966                     tdX:= Gear^.dX;
  1966                     tdX:= Gear^.dX;
  2006         end;
  2006         end;
  2007     if Gear^.Health = 0 then
  2007     if Gear^.Health = 0 then
  2008         begin
  2008         begin
  2009         gX := hwRound(Gear^.X);
  2009         gX := hwRound(Gear^.X);
  2010         gY := hwRound(Gear^.Y);
  2010         gY := hwRound(Gear^.Y);
  2011         if not sticky then
  2011         if (not sticky) then
  2012             begin
  2012             begin
  2013             if ((GameTicks and $3) = 0) and (Random(1) = 0) then
  2013             if ((GameTicks and $3) = 0) and (Random(1) = 0) then
  2014                 for i:= Random(2) downto 0 do
  2014                 for i:= Random(2) downto 0 do
  2015                     AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2015                     AddVisualGear(gX - 3 + Random(6), gY - 2, vgtSmoke);
  2016             end
  2016             end
  2045         AmmoShove(Gear, 30, 40);
  2045         AmmoShove(Gear, 30, 40);
  2046         HHGear^.State := HHGear^.State and (not gstNoDamage)
  2046         HHGear^.State := HHGear^.State and (not gstNoDamage)
  2047         end;
  2047         end;
  2048 
  2048 
  2049     HHGear^.dY := HHGear^.dY + cGravity;
  2049     HHGear^.dY := HHGear^.dY + cGravity;
  2050     if not (HHGear^.dY.isNegative) then
  2050     if (not HHGear^.dY.isNegative) then
  2051         begin
  2051         begin
  2052         HHGear^.State := HHGear^.State or gstMoving;
  2052         HHGear^.State := HHGear^.State or gstMoving;
  2053         DeleteGear(Gear);
  2053         DeleteGear(Gear);
  2054         AfterAttack;
  2054         AfterAttack;
  2055         exit
  2055         exit
  2154 procedure doStepAirAttackWork(Gear: PGear);
  2154 procedure doStepAirAttackWork(Gear: PGear);
  2155 begin
  2155 begin
  2156     AllInactive := false;
  2156     AllInactive := false;
  2157     Gear^.X := Gear^.X + cAirPlaneSpeed * Gear^.Tag;
  2157     Gear^.X := Gear^.X + cAirPlaneSpeed * Gear^.Tag;
  2158 
  2158 
  2159     if (Gear^.Health > 0)and(not (Gear^.X < Gear^.dX))and(Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  2159     if (Gear^.Health > 0) and (not (Gear^.X < Gear^.dX)) and (Gear^.X < Gear^.dX + cAirPlaneSpeed) then
  2160         begin
  2160         begin
  2161         dec(Gear^.Health);
  2161         dec(Gear^.Health);
  2162             case Gear^.State of 
  2162             case Gear^.State of 
  2163                 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  2163                 0: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAirBomb, 0, cBombsSpeed * Gear^.Tag, _0, 0);
  2164                 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed * Gear^.Tag, _0, 0);
  2164                 1: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtMine,    0, cBombsSpeed * Gear^.Tag, _0, 0);
  2245     ty := int2hwFloat(Gear^.Target.Y);
  2245     ty := int2hwFloat(Gear^.Target.Y);
  2246     x := HHGear^.X;
  2246     x := HHGear^.X;
  2247     y := HHGear^.Y;
  2247     y := HHGear^.Y;
  2248 
  2248 
  2249     if (Distance(tx - x, ty - y) > _256)
  2249     if (Distance(tx - x, ty - y) > _256)
  2250     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
  2250     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
  2251         begin
  2251         begin
  2252         PlaySound(sndDenied);
  2252         PlaySound(sndDenied);
  2253         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2253         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2254         HHGear^.State := HHGear^.State and (not gstAttacking);
  2254         HHGear^.State := HHGear^.State and (not gstAttacking);
  2255         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2255         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2307     HHGear: PGear;
  2307     HHGear: PGear;
  2308 begin
  2308 begin
  2309     AllInactive := false;
  2309     AllInactive := false;
  2310 
  2310 
  2311     HHGear := Gear^.Hedgehog^.Gear;
  2311     HHGear := Gear^.Hedgehog^.Gear;
  2312     if not TryPlaceOnLand(Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2,
  2312     if (not (TryPlaceOnLand(Gear^.Target.X - SpritesData[sprHHTelepMask].Width div 2,
  2313         Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2,
  2313         Gear^.Target.Y - SpritesData[sprHHTelepMask].Height div 2,
  2314         sprHHTelepMask, 0, false, false) then
  2314         sprHHTelepMask, 0, false, false))) then
  2315         begin
  2315         begin
  2316         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2316         HHGear^.Message := HHGear^.Message and (not gmAttack);
  2317         HHGear^.State := HHGear^.State and (not gstAttacking);
  2317         HHGear^.State := HHGear^.State and (not gstAttacking);
  2318         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2318         HHGear^.State := HHGear^.State or gstHHChooseTarget;
  2319         DeleteGear(Gear);
  2319         DeleteGear(Gear);
  2898     //fixes drill not exploding when touching HH bug
  2898     //fixes drill not exploding when touching HH bug
  2899     
  2899     
  2900     if (Gear^.Timer = 0) or ((t <> nil) and (t^.Count <> 0))
  2900     if (Gear^.Timer = 0) or ((t <> nil) and (t^.Count <> 0))
  2901     or ( ((Gear^.State and gsttmpFlag) = 0) and (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))))
  2901     or ( ((Gear^.State and gsttmpFlag) = 0) and (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))))
  2902 // CheckLandValue returns true if the type isn't matched
  2902 // CheckLandValue returns true if the type isn't matched
  2903     or (not CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible)) then
  2903     or (not (CheckLandValue(hwRound(Gear^.X), hwRound(Gear^.Y), lfIndestructible))) then
  2904         begin
  2904         begin
  2905         //out of time or exited ground
  2905         //out of time or exited ground
  2906         StopSoundChan(Gear^.SoundChannel);
  2906         StopSoundChan(Gear^.SoundChannel);
  2907         if (Gear^.State and gsttmpFlag) <> 0 then
  2907         if (Gear^.State and gsttmpFlag) <> 0 then
  2908             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound)
  2908             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound)
  2910             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  2910             doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 50, Gear^.Hedgehog, EXPLAutoSound);
  2911         DeleteGear(Gear);
  2911         DeleteGear(Gear);
  2912         exit
  2912         exit
  2913         end
  2913         end
  2914         
  2914         
  2915     else if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not TestCollisionXWithGear(Gear, hwSign(Gear^.dX))) then
  2915     else if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) = 0) and (not (TestCollisionXWithGear(Gear, hwSign(Gear^.dX)))) then
  2916         begin
  2916         begin
  2917         StopSoundChan(Gear^.SoundChannel);
  2917         StopSoundChan(Gear^.SoundChannel);
  2918         Gear^.Tag := 1;
  2918         Gear^.Tag := 1;
  2919         Gear^.doStep := @doStepDrill
  2919         Gear^.doStep := @doStepDrill
  2920         end;
  2920         end;
  3266     HHGear^.State := HHGear^.State or gstMoving;
  3266     HHGear^.State := HHGear^.State or gstMoving;
  3267 
  3267 
  3268     Gear^.X := HHGear^.X;
  3268     Gear^.X := HHGear^.X;
  3269     Gear^.Y := HHGear^.Y;
  3269     Gear^.Y := HHGear^.Y;
  3270 
  3270 
  3271     if not isUnderWater and hasBorder and ((HHGear^.X < _0)
  3271     if (not isUnderWater) and hasBorder and ((HHGear^.X < _0)
  3272     or (hwRound(HHGear^.X) > LAND_WIDTH)) then
  3272     or (hwRound(HHGear^.X) > LAND_WIDTH)) then
  3273         HHGear^.dY.isNegative:= false;
  3273         HHGear^.dY.isNegative:= false;
  3274         
  3274         
  3275     if ((Gear^.State and gsttmpFlag) = 0)
  3275     if ((Gear^.State and gsttmpFlag) = 0)
  3276     or (HHGear^.dY < _0) then
  3276     or (HHGear^.dY < _0) then
  3662         iscake:= (iterator^.Kind = gtCake);
  3662         iscake:= (iterator^.Kind = gtCake);
  3663 
  3663 
  3664         // won't port stuff that does not move towards the front/portal entrance
  3664         // won't port stuff that does not move towards the front/portal entrance
  3665         if iscake then
  3665         if iscake then
  3666             begin
  3666             begin
  3667             if not (((iterator^.X - Gear^.X)*ox + (iterator^.Y - Gear^.Y)*oy).isNegative) then
  3667             if (not (((iterator^.X - Gear^.X)*ox + (iterator^.Y - Gear^.Y)*oy).isNegative)) then
  3668                 continue;
  3668                 continue;
  3669             end
  3669             end
  3670         else
  3670         else
  3671             if not ((Gear^.dX*ox + Gear^.dY*oy).isNegative) then
  3671             if (not ((Gear^.dX*ox + Gear^.dY*oy).isNegative)) then
  3672                 continue;
  3672                 continue;
  3673 
  3673 
  3674         isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]);
  3674         isbullet:= (iterator^.Kind in [gtShotgunShot, gtDEagleShot, gtSniperRifleShot, gtSineGunShot]);
  3675 
  3675 
  3676         r:= int2hwFloat(iterator^.Radius);
  3676         r:= int2hwFloat(iterator^.Radius);
  3677 
  3677 
  3678         if not (isbullet or iscake) then
  3678         if (not (isbullet or iscake)) then
  3679             begin
  3679             begin
  3680             // wow! good candidate there, let's see if the distance and direction is okay!
  3680             // wow! good candidate there, let's see if the distance and direction is okay!
  3681             if hasdxy then
  3681             if hasdxy then
  3682                 begin
  3682                 begin
  3683                 s := r / Distance(iterator^.dX, iterator^.dY);
  3683                 s := r / Distance(iterator^.dX, iterator^.dY);
  3701         // calc gear offset in portal vector direction
  3701         // calc gear offset in portal vector direction
  3702         ox := (iterator^.X - Gear^.X);
  3702         ox := (iterator^.X - Gear^.X);
  3703         oy := (iterator^.Y - Gear^.Y);
  3703         oy := (iterator^.Y - Gear^.Y);
  3704         poffs:= (Gear^.dX * ox + Gear^.dY * oy);
  3704         poffs:= (Gear^.dX * ox + Gear^.dY * oy);
  3705 
  3705 
  3706         if not isBullet and poffs.isNegative then
  3706         if (not isBullet) and poffs.isNegative then
  3707             continue;
  3707             continue;
  3708 
  3708 
  3709         // only port bullets close to the portal
  3709         // only port bullets close to the portal
  3710         if isBullet and (not (hwAbs(poffs) < _3)) then
  3710         if isBullet and (not (hwAbs(poffs) < _3)) then
  3711             continue;
  3711             continue;
  3728         ny := Gear^.dX;
  3728         ny := Gear^.dX;
  3729         // ... decide where the top is based on the hog's direction when firing the portal
  3729         // ... decide where the top is based on the hog's direction when firing the portal
  3730         if Gear^.Elasticity.isNegative then
  3730         if Gear^.Elasticity.isNegative then
  3731             nx.isNegative := (not nx.isNegative)
  3731             nx.isNegative := (not nx.isNegative)
  3732         else
  3732         else
  3733             ny.isNegative := not ny.isNegative;
  3733             ny.isNegative := (not ny.isNegative);
  3734 
  3734 
  3735         // calc gear offset in portal normal vector direction
  3735         // calc gear offset in portal normal vector direction
  3736         noffs:= (nx * ox + ny * oy);
  3736         noffs:= (nx * ox + ny * oy);
  3737 
  3737 
  3738         if isBullet and (noffs.Round >= Longword(Gear^.Radius)) then
  3738         if isBullet and (noffs.Round >= Longword(Gear^.Radius)) then
  3739             continue;
  3739             continue;
  3740 
  3740 
  3741         // avoid gravity related loops of not really moving gear
  3741         // avoid gravity related loops of not really moving gear
  3742         if not (iscake or isbullet)
  3742         if (not (iscake or isbullet))
  3743         and (Gear^.dY.isNegative)
  3743         and (Gear^.dY.isNegative)
  3744         and (conPortal^.dY.isNegative)
  3744         and (conPortal^.dY.isNegative)
  3745         and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
  3745         and ((iterator^.dX.QWordValue + iterator^.dY.QWordValue) < _0_08.QWordValue)
  3746         and (iterator^.PortalCounter > 0) then
  3746         and (iterator^.PortalCounter > 0) then
  3747             continue;
  3747             continue;
  3762         nx := conPortal^.dY;
  3762         nx := conPortal^.dY;
  3763         ny := conPortal^.dX;
  3763         ny := conPortal^.dX;
  3764         if conPortal^.Elasticity.isNegative then
  3764         if conPortal^.Elasticity.isNegative then
  3765             nx.isNegative := (not nx.isNegative)
  3765             nx.isNegative := (not nx.isNegative)
  3766         else
  3766         else
  3767             ny.isNegative := not ny.isNegative;
  3767             ny.isNegative := (not ny.isNegative);
  3768 
  3768 
  3769         // inverse cake's normal movement direction,
  3769         // inverse cake's normal movement direction,
  3770         // as if it just walked through a hole
  3770         // as if it just walked through a hole
  3771         //if iscake then nspeed.isNegative:= not nspeed.isNegative;
  3771         //if iscake then nspeed.isNegative:= not nspeed.isNegative;
  3772 
  3772 
  3798             end;
  3798             end;
  3799 
  3799 
  3800         iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx;
  3800         iterator^.X := conPortal^.X + poffs * conPortal^.dX + noffs * nx;
  3801         iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny;
  3801         iterator^.Y := conPortal^.Y + poffs * conPortal^.dY + noffs * ny;
  3802 
  3802 
  3803         if not hasdxy and (not (conPortal^.dY.isNegative)) then
  3803         if (not hasdxy) and (not (conPortal^.dY.isNegative)) then
  3804             begin
  3804             begin
  3805             iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
  3805             iterator^.dY:= iterator^.dY + hwAbs(cGravity * (iterator^.Y - conPortal^.Y))
  3806             end;
  3806             end;
  3807 
  3807 
  3808         // see if the space on the exit side actually is enough
  3808         // see if the space on the exit side actually is enough
  3809 
  3809 
  3810         if not (isBullet or isCake) then
  3810         if (not (isBullet or isCake)) then
  3811             begin
  3811             begin
  3812             // TestCollisionXwithXYShift requires a hwFloat for xShift
  3812             // TestCollisionXwithXYShift requires a hwFloat for xShift
  3813             ox.QWordValue := _1.QWordValue;
  3813             ox.QWordValue := _1.QWordValue;
  3814             ox.isNegative := not iterator^.dX.isNegative;
  3814             ox.isNegative := not iterator^.dX.isNegative;
  3815 
  3815 
  3821 
  3821 
  3822             // check front
  3822             // check front
  3823             isCollision := TestCollisionY(iterator, sy)
  3823             isCollision := TestCollisionY(iterator, sy)
  3824                         or TestCollisionX(iterator, sx);
  3824                         or TestCollisionX(iterator, sx);
  3825 
  3825 
  3826             if not isCollision then
  3826             if (not isCollision) then
  3827                 begin
  3827                 begin
  3828                 // check center area (with half the radius so that the
  3828                 // check center area (with half the radius so that the
  3829                 // the square check won't check more pixels than we want to)
  3829                 // the square check won't check more pixels than we want to)
  3830                 iterator^.Radius := 1 + resetr div 2;
  3830                 iterator^.Radius := 1 + resetr div 2;
  3831                 rh := resetr div 4;
  3831                 rh := resetr div 4;
  3873             resetdx.QWordValue:= 4294967296 * 1152;
  3873             resetdx.QWordValue:= 4294967296 * 1152;
  3874     
  3874     
  3875             resetdy:=hwAbs(iterator^.dX*4);
  3875             resetdy:=hwAbs(iterator^.dX*4);
  3876             resetdy:= resetdy + hwPow(resetdy,3)/_6 + _3 * hwPow(resetdy,5) / _40 + _5 * hwPow(resetdy,7) / resety + resetx * hwPow(resetdy,9) / resetdx;
  3876             resetdy:= resetdy + hwPow(resetdy,3)/_6 + _3 * hwPow(resetdy,5) / _40 + _5 * hwPow(resetdy,7) / resety + resetx * hwPow(resetdy,9) / resetdx;
  3877             iterator^.Angle:= hwRound(resetdy*_2048 / _PI);
  3877             iterator^.Angle:= hwRound(resetdy*_2048 / _PI);
  3878             if not iterator^.dY.isNegative then iterator^.Angle:= 2048-iterator^.Angle;
  3878             if (not iterator^.dY.isNegative) then iterator^.Angle:= 2048-iterator^.Angle;
  3879             if iterator^.dX.isNegative then iterator^.Angle:= 4096-iterator^.Angle;
  3879             if iterator^.dX.isNegative then iterator^.Angle:= 4096-iterator^.Angle;
  3880             end
  3880             end
  3881         // VISUAL USE OF ANGLE ONLY
  3881         // VISUAL USE OF ANGLE ONLY
  3882         else if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtKamikaze) and (CurAmmoGear^.Hedgehog = iterator^.Hedgehog) then
  3882         else if (CurAmmoGear <> nil) and (CurAmmoGear^.Kind = gtKamikaze) and (CurAmmoGear^.Hedgehog = iterator^.Hedgehog) then
  3883             begin
  3883             begin
  3890         and (iterator = CurrentHedgehog^.Gear)
  3890         and (iterator = CurrentHedgehog^.Gear)
  3891         and (CurAmmoGear <> nil)
  3891         and (CurAmmoGear <> nil)
  3892         and (CurAmmoGear^.Kind =gtRope) then
  3892         and (CurAmmoGear^.Kind =gtRope) then
  3893                CurAmmoGear^.PortalCounter:= 1;
  3893                CurAmmoGear^.PortalCounter:= 1;
  3894 
  3894 
  3895         if not isbullet and (iterator^.State and gstInvisible = 0) 
  3895         if (not isbullet) and (iterator^.State and gstInvisible = 0)
  3896         and (iterator^.Kind <> gtFlake) then
  3896         and (iterator^.Kind <> gtFlake) then
  3897             FollowGear := iterator;
  3897             FollowGear := iterator;
  3898 
  3898 
  3899         // store X/Y values of exit for net bullet trail
  3899         // store X/Y values of exit for net bullet trail
  3900         if isbullet then
  3900         if isbullet then
  3952         begin
  3952         begin
  3953         Gear^.State := Gear^.State or gstCollision;
  3953         Gear^.State := Gear^.State or gstCollision;
  3954         Gear^.State := Gear^.State and (not gstMoving);
  3954         Gear^.State := Gear^.State and (not gstMoving);
  3955         
  3955         
  3956         if (Land[y, x] and lfBouncy <> 0)
  3956         if (Land[y, x] and lfBouncy <> 0)
  3957         or (not CalcSlopeTangent(Gear, x, y, tx, ty, 255))
  3957         or (not (CalcSlopeTangent(Gear, x, y, tx, ty, 255)))
  3958         or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
  3958         or (DistanceI(tx,ty) < _12) then // reject shots at too irregular terrain
  3959             begin
  3959             begin
  3960             loadNewPortalBall(Gear, true);
  3960             loadNewPortalBall(Gear, true);
  3961             EXIT;
  3961             EXIT;
  3962             end;
  3962             end;
  3965         s := _1/DistanceI(tx,ty);
  3965         s := _1/DistanceI(tx,ty);
  3966         Gear^.dX :=  s * ty;
  3966         Gear^.dX :=  s * ty;
  3967         Gear^.dY := -s * tx;
  3967         Gear^.dY := -s * tx;
  3968 
  3968 
  3969         Gear^.DirAngle := DxDy2Angle(-Gear^.dY,Gear^.dX);
  3969         Gear^.DirAngle := DxDy2Angle(-Gear^.dY,Gear^.dX);
  3970         if not Gear^.dX.isNegative then
  3970         if (not Gear^.dX.isNegative) then
  3971             Gear^.DirAngle := 180-Gear^.DirAngle;
  3971             Gear^.DirAngle := 180-Gear^.DirAngle;
  3972 
  3972 
  3973         if ((Gear^.LinkedGear = nil)
  3973         if ((Gear^.LinkedGear = nil)
  3974         or (hwRound(Distance(Gear^.X - Gear^.LinkedGear^.X,Gear^.Y-Gear^.LinkedGear^.Y)) >=Gear^.Radius*2)) then
  3974         or (hwRound(Distance(Gear^.X - Gear^.LinkedGear^.X,Gear^.Y-Gear^.LinkedGear^.Y)) >=Gear^.Radius*2)) then
  3975             begin
  3975             begin
  4055                 begin
  4055                 begin
  4056                 // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
  4056                 // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
  4057                 iterator:= GearsList;
  4057                 iterator:= GearsList;
  4058                 while iterator <> nil do
  4058                 while iterator <> nil do
  4059                     begin
  4059                     begin
  4060                     if not (iterator^.Kind in [gtPortal, gtAirAttack, gtKnife]) and ((iterator^.Hedgehog <> CurrentHedgehog)
  4060                     if (not (iterator^.Kind in [gtPortal, gtAirAttack, gtKnife])) and ((iterator^.Hedgehog <> CurrentHedgehog)
  4061                     or ((iterator^.Message and gmAllStoppable) = 0)) then
  4061                     or ((iterator^.Message and gmAllStoppable) = 0)) then
  4062                             begin
  4062                             begin
  4063                             iterator^.Active:= true;
  4063                             iterator^.Active:= true;
  4064                             if iterator^.dY.QWordValue = 0 then
  4064                             if iterator^.dY.QWordValue = 0 then
  4065                                 iterator^.dY.isNegative:= false;
  4065                                 iterator^.dY.isNegative:= false;
  5155     gi := GearsList;
  5155     gi := GearsList;
  5156     while gi <> nil do
  5156     while gi <> nil do
  5157         begin
  5157         begin
  5158         with gi^ do CheckSum:= CheckSum xor X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac;
  5158         with gi^ do CheckSum:= CheckSum xor X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac;
  5159         AddRandomness(CheckSum);
  5159         AddRandomness(CheckSum);
  5160         if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and not gstTmpFlag;
  5160         if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and (not gstTmpFlag);
  5161         gi := gi^.NextGear
  5161         gi := gi^.NextGear
  5162         end;
  5162         end;
  5163     AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
  5163     AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
  5164     DeleteGear(Gear)
  5164     DeleteGear(Gear)
  5165     end;
  5165     end;
  5255         end
  5255         end
  5256     else if (GameTicks and $FF = 0) then
  5256     else if (GameTicks and $FF = 0) then
  5257         begin
  5257         begin
  5258         tdX:= HHGear^.X-Gear^.X;
  5258         tdX:= HHGear^.X-Gear^.X;
  5259         dir:= hwSign(tdX);
  5259         dir:= hwSign(tdX);
  5260         if not TestCollisionX(Gear, dir) then
  5260         if (not TestCollisionX(Gear, dir)) then
  5261             Gear^.X:= Gear^.X + signAs(_1,tdX);
  5261             Gear^.X:= Gear^.X + signAs(_1,tdX);
  5262         if TestCollisionXwithXYShift(Gear, signAs(_10,tdX), 0, dir) then
  5262         if TestCollisionXwithXYShift(Gear, signAs(_10,tdX), 0, dir) then
  5263             begin
  5263             begin
  5264             Gear^.dX:= SignAs(_0_15, tdX);
  5264             Gear^.dX:= SignAs(_0_15, tdX);
  5265             Gear^.dY:= -_0_3;
  5265             Gear^.dY:= -_0_3;
  5328         AddGearCI(Gear)
  5328         AddGearCI(Gear)
  5329         end
  5329         end
  5330     else if GameTicks and $3F = 0 then
  5330     else if GameTicks and $3F = 0 then
  5331         begin
  5331         begin
  5332         if  (TestCollisionYwithGear(Gear, -1) = 0)
  5332         if  (TestCollisionYwithGear(Gear, -1) = 0)
  5333         and (not TestCollisionXwithGear(Gear, 1))
  5333         and (not (TestCollisionXwithGear(Gear, 1)))
  5334         and (not TestCollisionXwithGear(Gear, -1))
  5334         and (not (TestCollisionXwithGear(Gear, -1)))
  5335         and (TestCollisionYwithGear(Gear, 1) = 0) then Gear^.State:= Gear^.State and (not gstCollision) or gstMoving;
  5335         and (TestCollisionYwithGear(Gear, 1) = 0) then Gear^.State:= Gear^.State and (not gstCollision) or gstMoving;
  5336         end
  5336         end
  5337 end;
  5337 end;
  5338 (*
  5338 (*
  5339  This didn't end up getting used, but, who knows, might be reasonable for javellin or something
  5339  This didn't end up getting used, but, who knows, might be reasonable for javellin or something