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 |
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 |