hedgewars/uGearsHandlersMess.pas
changeset 10015 4feced261c68
parent 10011 ead5e4b21671
parent 9954 bf51bc7e2808
child 10040 4ac87acbaed9
equal deleted inserted replaced
10014:56d2f2d5aad8 10015:4feced261c68
    22  * Important: Since gears change the course of the game, calculations that
    22  * Important: Since gears change the course of the game, calculations that
    23  *            lead to different results for different clients/players/machines
    23  *            lead to different results for different clients/players/machines
    24  *            should NOT occur!
    24  *            should NOT occur!
    25  *            Use safe functions and data types! (e.g. GetRandom() and hwFloat)
    25  *            Use safe functions and data types! (e.g. GetRandom() and hwFloat)
    26  *)
    26  *)
    27  
    27 
    28  {$INCLUDE "options.inc"}
    28  {$INCLUDE "options.inc"}
    29 
    29 
    30 unit uGearsHandlersMess;
    30 unit uGearsHandlersMess;
    31 interface
    31 interface
    32 uses uTypes, uFloat;
    32 uses uTypes, uFloat;
   392         begin
   392         begin
   393         xland:= TestCollisionXwithGear(Gear, -hwSign(Gear^.dX));
   393         xland:= TestCollisionXwithGear(Gear, -hwSign(Gear^.dX));
   394         if xland <> 0 then collH := -hwSign(Gear^.dX)
   394         if xland <> 0 then collH := -hwSign(Gear^.dX)
   395         end;
   395         end;
   396     //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
   396     //if Gear^.AdvBounce and (collV <>0) and (collH <> 0) and (hwSqr(tdX) + hwSqr(tdY) > _0_08) then
   397     if (collV <> 0) and (collH <> 0) and 
   397     if (collV <> 0) and (collH <> 0) and
   398        (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then
   398        (((Gear^.AdvBounce=1) and ((collV=-1) or ((tdX.QWordValue + tdY.QWordValue) > _0_2.QWordValue)))) then
   399  //or ((xland or land) and lfBouncy <> 0)) then
   399  //or ((xland or land) and lfBouncy <> 0)) then
   400         begin
   400         begin
   401         if (xland or land) and lfBouncy = 0 then
   401         if (xland or land) and lfBouncy = 0 then
   402             begin
   402             begin
   434     else
   434     else
   435         Gear^.State := Gear^.State or gstMoving;
   435         Gear^.State := Gear^.State or gstMoving;
   436 
   436 
   437     if ((xland or land) and lfBouncy <> 0) and (Gear^.dX.QWordValue < _0_15.QWordValue) and (Gear^.dY.QWordValue < _0_15.QWordValue) then
   437     if ((xland or land) and lfBouncy <> 0) and (Gear^.dX.QWordValue < _0_15.QWordValue) and (Gear^.dY.QWordValue < _0_15.QWordValue) then
   438         Gear^.State := Gear^.State or gstCollision;
   438         Gear^.State := Gear^.State or gstCollision;
   439     
   439 
   440     if ((xland or land) and lfBouncy <> 0) and (Gear^.Radius >= 3) and
   440     if ((xland or land) and lfBouncy <> 0) and (Gear^.Radius >= 3) and
   441        ((Gear^.dX.QWordValue > _0_15.QWordValue) or (Gear^.dY.QWordValue > _0_15.QWordValue)) then
   441        ((Gear^.dX.QWordValue > _0_15.QWordValue) or (Gear^.dY.QWordValue > _0_15.QWordValue)) then
   442         begin
   442         begin
   443         boing:= AddVisualGear(gX, gY, vgtStraightShot, 0, false, 1);
   443         boing:= AddVisualGear(gX, gY, vgtStraightShot, 0, false, 1);
   444         if boing <> nil then
   444         if boing <> nil then
   758         draw:= true;
   758         draw:= true;
   759     xx:= hwRound(Gear^.X);
   759     xx:= hwRound(Gear^.X);
   760     yy:= hwRound(Gear^.Y);
   760     yy:= hwRound(Gear^.Y);
   761     if draw and (WorldEdge = weWrap) and ((xx < LongInt(leftX) + 3) or (xx > LongInt(rightX) - 3)) then
   761     if draw and (WorldEdge = weWrap) and ((xx < LongInt(leftX) + 3) or (xx > LongInt(rightX) - 3)) then
   762         begin
   762         begin
   763         if xx < LongInt(leftX) + 3 then 
   763         if xx < LongInt(leftX) + 3 then
   764              xx:= rightX-3
   764              xx:= rightX-3
   765         else xx:= leftX+3;
   765         else xx:= leftX+3;
   766         Gear^.X:= int2hwFloat(xx)
   766         Gear^.X:= int2hwFloat(xx)
   767         end
   767         end
   768     end
   768     end
  1052         if Gear^.Timer = 0 then
  1052         if Gear^.Timer = 0 then
  1053             begin
  1053             begin
  1054             // no need to display remaining time anymore
  1054             // no need to display remaining time anymore
  1055             Gear^.RenderTimer:= false;
  1055             Gear^.RenderTimer:= false;
  1056             // bee can drown when timer reached 0
  1056             // bee can drown when timer reached 0
  1057             Gear^.State:= Gear^.State and not gstSubmersible;
  1057             Gear^.State:= Gear^.State and (not gstSubmersible);
  1058             end;
  1058             end;
  1059         end;
  1059         end;
  1060 end;
  1060 end;
  1061 
  1061 
  1062 procedure doStepBee(Gear: PGear);
  1062 procedure doStepBee(Gear: PGear);
  1233         y := hwRound(Gear^.Y);
  1233         y := hwRound(Gear^.Y);
  1234 
  1234 
  1235         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then
  1235         if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then
  1236             inc(Gear^.Damage);
  1236             inc(Gear^.Damage);
  1237         // let's interrupt before a collision to give portals a chance to catch the bullet
  1237         // let's interrupt before a collision to give portals a chance to catch the bullet
  1238         if (Gear^.Damage = 1) and (Gear^.Tag = 0) and not(CheckLandValue(x, y, lfLandMask)) then
  1238         if (Gear^.Damage = 1) and (Gear^.Tag = 0) and (not CheckLandValue(x, y, lfLandMask)) then
  1239             begin
  1239             begin
  1240             Gear^.Tag := 1;
  1240             Gear^.Tag := 1;
  1241             Gear^.Damage := 0;
  1241             Gear^.Damage := 0;
  1242             Gear^.X := Gear^.X - Gear^.dX;
  1242             Gear^.X := Gear^.X - Gear^.dX;
  1243             Gear^.Y := Gear^.Y - Gear^.dY;
  1243             Gear^.Y := Gear^.Y - Gear^.dY;
  1770                     PlaySound(sndMineTick);
  1770                     PlaySound(sndMineTick);
  1771                 dec(Gear^.Timer);
  1771                 dec(Gear^.Timer);
  1772                 end
  1772                 end
  1773             end
  1773             end
  1774     else // gsttmpFlag = 0
  1774     else // gsttmpFlag = 0
  1775         if ((GameFlags and gfInfAttack = 0) and ((TurnTimeLeft = 0) or (Gear^.Hedgehog^.Gear = nil))) 
  1775         if ((GameFlags and gfInfAttack = 0) and ((TurnTimeLeft = 0) or (Gear^.Hedgehog^.Gear = nil)))
  1776         or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) then
  1776         or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime)) then
  1777             Gear^.State := Gear^.State or gsttmpFlag;
  1777             Gear^.State := Gear^.State or gsttmpFlag;
  1778 end;
  1778 end;
  1779 
  1779 
  1780 ////////////////////////////////////////////////////////////////////////////////
  1780 ////////////////////////////////////////////////////////////////////////////////
  1804     dxdy: hwFloat;
  1804     dxdy: hwFloat;
  1805 begin
  1805 begin
  1806     if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then
  1806     if (Gear^.dY.QWordValue = 0) and (Gear^.dY.QWordValue = 0) and (TestCollisionYwithGear(Gear, 1) = 0) then
  1807         SetLittle(Gear^.dY);
  1807         SetLittle(Gear^.dY);
  1808     Gear^.State := Gear^.State or gstAnimation;
  1808     Gear^.State := Gear^.State or gstAnimation;
  1809     if Gear^.Health < cBarrelHealth then Gear^.State:= Gear^.State and not gstFrozen;
  1809     if Gear^.Health < cBarrelHealth then Gear^.State:= Gear^.State and (not gstFrozen);
  1810 
  1810 
  1811     if ((Gear^.dX.QWordValue <> 0)
  1811     if ((Gear^.dX.QWordValue <> 0)
  1812     or (Gear^.dY.QWordValue <> 0))  then
  1812     or (Gear^.dY.QWordValue <> 0))  then
  1813         begin
  1813         begin
  1814         DeleteCI(Gear);
  1814         DeleteCI(Gear);
  1890         with CurrentHedgehog^ do
  1890         with CurrentHedgehog^ do
  1891             if Gear <> nil then
  1891             if Gear <> nil then
  1892                 Gear^.Message := Gear^.Message and (not (gmLJump or gmHJump));
  1892                 Gear^.Message := Gear^.Message and (not (gmLJump or gmHJump));
  1893         exit
  1893         exit
  1894         end;
  1894         end;
  1895     if (k = gtExplosives) and (Gear^.Health < cBarrelHealth) then Gear^.State:= Gear^.State and not gstFrozen;
  1895     if (k = gtExplosives) and (Gear^.Health < cBarrelHealth) then Gear^.State:= Gear^.State and (not gstFrozen);
  1896 
  1896 
  1897     if ((k <> gtExplosives) and (Gear^.Damage > 0)) or ((k = gtExplosives) and (Gear^.Health<=0)) then
  1897     if ((k <> gtExplosives) and (Gear^.Damage > 0)) or ((k = gtExplosives) and (Gear^.Health<=0)) then
  1898         begin
  1898         begin
  1899         x := hwRound(Gear^.X);
  1899         x := hwRound(Gear^.X);
  1900         y := hwRound(Gear^.Y);
  1900         y := hwRound(Gear^.Y);
  2161             PlaySound(sndVaporize);
  2161             PlaySound(sndVaporize);
  2162             DeleteGear(Gear);
  2162             DeleteGear(Gear);
  2163             exit
  2163             exit
  2164             end
  2164             end
  2165         end
  2165         end
  2166     else 
  2166     else
  2167         begin
  2167         begin
  2168         if (Gear^.Timer = 1) and (GameTicks and $3 = 0) then
  2168         if (Gear^.Timer = 1) and (GameTicks and $3 = 0) then
  2169             begin
  2169             begin
  2170             Gear^.Y:= Gear^.Y+_6;
  2170             Gear^.Y:= Gear^.Y+_6;
  2171             if (landPixel and lfIce <> 0) or (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
  2171             if (landPixel and lfIce <> 0) or (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
  2469     doStepFallingGear(Gear);
  2469     doStepFallingGear(Gear);
  2470     if (Gear^.State and gstCollision) <> 0 then
  2470     if (Gear^.State and gstCollision) <> 0 then
  2471         begin
  2471         begin
  2472         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  2472         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, Gear^.Hedgehog, EXPLAutoSound);
  2473         DeleteGear(Gear);
  2473         DeleteGear(Gear);
       
  2474         {$IFNDEF PAS2C}
  2474         with mobileRecord do
  2475         with mobileRecord do
  2475             if (performRumble <> nil) and (not fastUntilLag) then
  2476             if (performRumble <> nil) and (not fastUntilLag) then
  2476                 performRumble(kSystemSoundID_Vibrate);
  2477                 performRumble(kSystemSoundID_Vibrate);
       
  2478         {$ENDIF}
  2477         exit
  2479         exit
  2478         end;
  2480         end;
  2479     if (GameTicks and $3F) = 0 then
  2481     if (GameTicks and $3F) = 0 then
  2480         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
  2482         AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeTrace)
  2481 end;
  2483 end;
  2500 
  2502 
  2501     LandFlags:= 0;
  2503     LandFlags:= 0;
  2502     if Gear^.AmmoType = amRubber then LandFlags:= lfBouncy
  2504     if Gear^.AmmoType = amRubber then LandFlags:= lfBouncy
  2503     else if cIce then LandFlags:= lfIce;
  2505     else if cIce then LandFlags:= lfIce;
  2504 
  2506 
  2505     if ((Distance(tx - x, ty - y) > _256) and ((WorldEdge <> weWrap) or 
  2507     if ((Distance(tx - x, ty - y) > _256) and ((WorldEdge <> weWrap) or
  2506             (
  2508             (
  2507             (Distance(tx - int2hwFloat(rightX+(rx-leftX)), ty - y) > _256) and
  2509             (Distance(tx - int2hwFloat(rightX+(rx-leftX)), ty - y) > _256) and
  2508             (Distance(tx - int2hwFloat(leftX-(rightX-rx)), ty - y) > _256)
  2510             (Distance(tx - int2hwFloat(leftX-(rightX-rx)), ty - y) > _256)
  2509             )))
  2511             )))
  2510     or (not TryPlaceOnLand(Gear^.Target.X - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Width div 2, Gear^.Target.Y - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Height div 2, Ammoz[Gear^.AmmoType].PosSprite, Gear^.State, true, false, LandFlags)) then
  2512     or (not TryPlaceOnLand(Gear^.Target.X - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Width div 2, Gear^.Target.Y - SpritesData[Ammoz[Gear^.AmmoType].PosSprite].Height div 2, Ammoz[Gear^.AmmoType].PosSprite, Gear^.State, true, false, LandFlags)) then
  4613     AmmoShove(Gear, 0, 80);
  4615     AmmoShove(Gear, 0, 80);
  4614     Gear^.dX.isNegative := not Gear^.dX.isNegative;
  4616     Gear^.dX.isNegative := not Gear^.dX.isNegative;
  4615     Gear^.dY.isNegative := not Gear^.dY.isNegative;
  4617     Gear^.dY.isNegative := not Gear^.dY.isNegative;
  4616 
  4618 
  4617     Gear^.doStep := @doStepSineGunShotWork;
  4619     Gear^.doStep := @doStepSineGunShotWork;
       
  4620     {$IFNDEF PAS2C}
  4618     with mobileRecord do
  4621     with mobileRecord do
  4619         if (performRumble <> nil) and (not fastUntilLag) then
  4622         if (performRumble <> nil) and (not fastUntilLag) then
  4620             performRumble(kSystemSoundID_Vibrate);
  4623             performRumble(kSystemSoundID_Vibrate);
       
  4624     {$ENDIF}
  4621 end;
  4625 end;
  4622 
  4626 
  4623 ////////////////////////////////////////////////////////////////////////////////
  4627 ////////////////////////////////////////////////////////////////////////////////
  4624 procedure doStepFlamethrowerWork(Gear: PGear);
  4628 procedure doStepFlamethrowerWork(Gear: PGear);
  4625 var
  4629 var
  5378         begin
  5382         begin
  5379         StopSoundChan(Gear^.SoundChannel);
  5383         StopSoundChan(Gear^.SoundChannel);
  5380         Gear^.SoundChannel:= -1;
  5384         Gear^.SoundChannel:= -1;
  5381         if GameTicks mod 40 = 0 then dec(Gear^.Health)
  5385         if GameTicks mod 40 = 0 then dec(Gear^.Health)
  5382         end
  5386         end
  5383     else 
  5387     else
  5384         begin
  5388         begin
  5385         if Gear^.SoundChannel = -1 then
  5389         if Gear^.SoundChannel = -1 then
  5386             Gear^.SoundChannel := LoopSound(sndIceBeam);
  5390             Gear^.SoundChannel := LoopSound(sndIceBeam);
  5387         if GameTicks mod 10 = 0 then dec(Gear^.Health)
  5391         if GameTicks mod 10 = 0 then dec(Gear^.Health)
  5388         end
  5392         end
  5485                     landRect.x := min(max(target.x - iceRadius, 0), LAND_WIDTH - 1);
  5489                     landRect.x := min(max(target.x - iceRadius, 0), LAND_WIDTH - 1);
  5486                     landRect.y := min(max(target.y - iceRadius, 0), LAND_HEIGHT - 1);
  5490                     landRect.y := min(max(target.y - iceRadius, 0), LAND_HEIGHT - 1);
  5487                     landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1);
  5491                     landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1);
  5488                     landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1);
  5492                     landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1);
  5489                     UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);
  5493                     UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);
  5490                     
  5494 
  5491                     // Freeze nearby mines/explosives/cases too
  5495                     // Freeze nearby mines/explosives/cases too
  5492                     iter := GearsList;
  5496                     iter := GearsList;
  5493                     while iter <> nil do
  5497                     while iter <> nil do
  5494                         begin
  5498                         begin
  5495                         if (iter^.State and gstFrozen = 0) and
  5499                         if (iter^.State and gstFrozen = 0) and
  5496                            ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine)) and 
  5500                            ((iter^.Kind = gtExplosives) or (iter^.Kind = gtCase) or (iter^.Kind = gtMine)) and
  5497                            (abs(iter^.X.Round-target.x)+abs(iter^.Y.Round-target.y)+2<2*iceRadius) and (Distance(iter^.X-int2hwFloat(target.x),iter^.Y-int2hwFloat(target.y))<int2hwFloat(iceRadius*2)) then
  5501                            (abs(LongInt(iter^.X.Round) - target.x) + abs(LongInt(iter^.Y.Round) - target.y) + 2 < 2 * iceRadius)
       
  5502                            and (Distance(iter^.X - int2hwFloat(target.x), iter^.Y - int2hwFloat(target.y)) < int2hwFloat(iceRadius * 2)) then
  5498                             begin
  5503                             begin
  5499                             for t:= 0 to 5 do
  5504                             for t:= 0 to 5 do
  5500                                 begin
  5505                                 begin
  5501                                 vg:= AddVisualGear(hwRound(iter^.X)+random(4)-8, hwRound(iter^.Y)+random(8), vgtDust, 1);
  5506                                 vg:= AddVisualGear(hwRound(iter^.X)+random(4)-8, hwRound(iter^.Y)+random(8), vgtDust, 1);
  5502                                 if vg <> nil then
  5507                                 if vg <> nil then
  5619     gi := GearsList;
  5624     gi := GearsList;
  5620     while gi <> nil do
  5625     while gi <> nil do
  5621         begin
  5626         begin
  5622         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;
  5627         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;
  5623         AddRandomness(CheckSum);
  5628         AddRandomness(CheckSum);
  5624         if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and not gstTmpFlag;
  5629         if gi^.Kind = gtGenericFaller then gi^.State:= gi^.State and (not gstTmpFlag);
  5625         gi := gi^.NextGear
  5630         gi := gi^.NextGear
  5626         end;
  5631         end;
  5627     AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
  5632     AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
  5628     DeleteGear(Gear)
  5633     DeleteGear(Gear)
  5629     end;
  5634     end;