--- a/hedgewars/uGearsHandlersMess.pas Sat Jul 11 17:35:36 2020 +0300
+++ b/hedgewars/uGearsHandlersMess.pas Sat Jul 11 19:03:14 2020 +0300
@@ -7286,9 +7286,76 @@
end;
end;
+function CheckSentryDestroyed(Sentry: PGear; damagedState: LongInt): Boolean;
+begin
+ CheckSentryDestroyed := false;
+ if Sentry^.Damage > 0 then
+ begin
+ dec(Sentry^.Health, Sentry^.Damage);
+ Sentry^.Damage := 0;
+ if Sentry^.Health <= 0 then
+ begin
+ doMakeExplosion(hwRound(Sentry^.X), hwRound(Sentry^.Y), Sentry^.Boom, Sentry^.Hedgehog, EXPLAutoSound);
+ DeleteGear(Sentry);
+ CheckSentryDestroyed := true;
+ exit;
+ end
+ else
+ ResetSentryState(Sentry, damagedState, 10000)
+ end;
+
+ if ((Sentry^.Health * 100) < random(cSentryHealth * 90)) and ((GameTicks and $FF) = 0) then
+ if Sentry^.Health * 2 < cSentryHealth then
+ AddVisualGear(hwRound(Sentry^.X) - 8 + Random(16), hwRound(Sentry^.Y) - 2, vgtSmoke)
+ else
+ AddVisualGear(hwRound(Sentry^.X) - 8 + Random(16), hwRound(Sentry^.Y) - 2, vgtSmokeWhite);
+end;
+
+procedure AimSentry(Sentry: PGear);
+var HHGear: PGear;
+begin
+ if CurrentHedgehog <> nil then
+ begin
+ HHGear := CurrentHedgehog^.Gear;
+ if HHGear <> nil then
+ begin
+ Sentry^.Target.X := Sentry^.Target.X + hwSign(HHGear^.X - int2hwFloat(Sentry^.Target.X));
+ Sentry^.Target.Y := Sentry^.Target.Y + hwSign(HHGear^.Y - int2hwFloat(Sentry^.Target.Y));
+ end;
+ end;
+end;
+
+procedure MakeSentryShot(Sentry: PGear);
+var bullet: PGear;
+ distX, distY, invDistance: HwFloat;
+begin
+ distX := int2hwFloat(Sentry^.Target.X) - Sentry^.X;
+ distY := int2hwFloat(Sentry^.Target.Y) - Sentry^.Y;
+ invDistance := _1 / Distance(distX, distY);
+ distX := distX * invDistance;
+ distY := distY * invDistance;
+
+ bullet := AddGear(
+ hwRound(Sentry^.X), hwRound(Sentry^.Y),
+ gtMinigunBullet, 0,
+ distX * _0_9 + rndSign(getRandomf * _0_1),
+ distY * _0_9 + rndSign(getRandomf * _0_1),
+ 0);
+
+ bullet^.Karma := 12;
+ bullet^.Pos := 1;
+ bullet^.WDTimer := GameTicks;
+ bullet^.PortalCounter := 1;
+ bullet^.Elasticity := Sentry^.X;
+ bullet^.Friction := Sentry^.Y;
+ bullet^.Data := Pointer(Sentry);
+
+ CreateShellForGear(Sentry, Sentry^.WDTimer and 1);
+ PlaySound(sndGun);
+end;
+
procedure doStepSentryLand(Gear: PGear);
-var HHGear, bullet: PGear;
- distX, distY, invDistance: HwFloat;
+var HHGear: PGear;
const sentry_Idle = 0;
sentry_Walking = 1;
sentry_Aiming = 2;
@@ -7300,25 +7367,8 @@
if CheckGearDrowning(Gear) then
exit;
- if Gear^.Damage > 0 then
- begin
- dec(Gear^.Health, Gear^.Damage);
- Gear^.Damage := 0;
- if Gear^.Health <= 0 then
- begin
- doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
- DeleteGear(Gear);
- exit;
- end;
-
- ResetSentryState(Gear, sentry_Reloading, 10000)
- end;
-
- if ((Gear^.Health * 100) < random(cSentryHealth * 90)) and ((GameTicks and $FF) = 0) then
- if Gear^.Health * 2 < cSentryHealth then
- AddVisualGear(hwRound(Gear^.X) - 8 + Random(16), hwRound(Gear^.Y) - 2, vgtSmoke)
- else
- AddVisualGear(hwRound(Gear^.X) - 8 + Random(16), hwRound(Gear^.Y) - 2, vgtSmokeWhite);
+ if CheckSentryDestroyed(Gear, sentry_Reloading) then
+ exit;
if Gear^.dY.isNegative or (TestCollisionYwithGear(Gear, 1) = 0) then
begin
@@ -7396,39 +7446,10 @@
end
else if Gear^.Tag = sentry_Attacking then
begin
- distX := int2hwFloat(Gear^.Target.X) - Gear^.X;
- distY := int2hwFloat(Gear^.Target.Y) - Gear^.Y;
- invDistance := _1 / Distance(distX, distY);
- distX := distX * invDistance;
- distY := distY * invDistance;
-
- bullet := AddGear(
- hwRound(Gear^.X), hwRound(Gear^.Y),
- gtMinigunBullet, 0,
- distX * _0_9 + rndSign(getRandomf * _0_1),
- distY * _0_9 + rndSign(getRandomf * _0_1),
- 0);
-
- bullet^.Karma := 12;
- bullet^.Pos := 1;
- bullet^.WDTimer := GameTicks;
- bullet^.PortalCounter := 1;
- bullet^.Elasticity := Gear^.X;
- bullet^.Friction := Gear^.Y;
- bullet^.Data := Pointer(Gear);
-
- CreateShellForGear(Gear, Gear^.WDTimer and 1);
- PlaySound(sndGun);
+ MakeSentryShot(Gear);
if Gear^.WDTimer = 0 then
- begin
- Gear^.Target.X := 0;
- Gear^.Target.Y := 0;
- ClearGlobalHitOrderLeq(Gear^.Karma);
- Gear^.Karma := 0;
- Gear^.Tag := sentry_Reloading;
- Gear^.Timer := 6000 + GetRandom(2000);
- end
+ ResetSentryState(Gear, sentry_Reloading, 6000 + GetRandom(2000))
else
begin
dec(Gear^.WDTimer);
@@ -7443,15 +7464,8 @@
Gear^.Timer := 0
end;
- if ((GameTicks and $1F) = 0)
- and (Gear^.Tag = sentry_Aiming)
- and (CurrentHedgehog <> nil)
- and (CurrentHedgehog^.Gear <> nil) then
- begin
- HHGear := CurrentHedgehog^.Gear;
- Gear^.Target.X := Gear^.Target.X + hwSign(HHGear^.X - int2hwFloat(Gear^.Target.X));
- Gear^.Target.Y := Gear^.Target.Y + hwSign(HHGear^.Y - int2hwFloat(Gear^.Target.Y));
- end;
+ if ((GameTicks and $1F) = 0) and (Gear^.Tag = sentry_Aiming) then
+ AimSentry(Gear);
if ((GameTicks and $FF) = 0)
and (Gear^.Tag in [sentry_Idle, sentry_Walking])
@@ -7472,6 +7486,12 @@
end;
procedure doStepSentryWater(Gear: PGear);
+var HHGear: PGear;
+const sentry_Idle = 0;
+ sentry_Walking = 1;
+ sentry_Aiming = 2;
+ sentry_Attacking = 3;
+ sentry_Reloading = 4;
begin
if Gear^.Tag < 0 then
begin
@@ -7485,6 +7505,84 @@
Gear^.Tag := -1;
exit;
end;
+
+ if CheckSentryDestroyed(Gear, sentry_Reloading) then
+ exit;
+
+ if Gear^.Timer > 0 then dec(Gear^.Timer);
+
+ if Gear^.Timer = 0 then
+ begin
+ if Gear^.Tag = sentry_Idle then
+ begin
+ Gear^.Tag := sentry_Walking;
+ Gear^.Timer := 3000 + GetRandom(3000);
+ Gear^.dX.isNegative := GetRandom(2) = 1;
+ if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) <> 0 then
+ Gear^.dX.isNegative := not Gear^.dX.isNegative;
+ end
+ else if Gear^.Tag in [sentry_Walking, sentry_Reloading] then
+ begin
+ Gear^.Tag := sentry_Idle;
+ Gear^.Timer := 1000 + GetRandom(1000);
+ end
+ else if Gear^.Tag = sentry_Aiming then
+ begin
+ if CheckSentryAttackRange(Gear, int2hwFloat(Gear^.Target.X), int2hwFloat(Gear^.Target.Y)) then
+ begin
+ Gear^.WDTimer := 5 + GetRandom(3);
+ Gear^.Tag := sentry_Attacking;
+ Gear^.Timer := 100;
+ end
+ else
+ begin
+ Gear^.Target.X := 0;
+ Gear^.Target.Y := 0;
+ Gear^.Tag := sentry_Idle;
+ Gear^.Timer := 5000;
+ end
+ end
+ else if Gear^.Tag = sentry_Attacking then
+ begin
+ MakeSentryShot(Gear);
+
+ if Gear^.WDTimer = 0 then
+ ResetSentryState(Gear, sentry_Reloading, 6000 + GetRandom(2000))
+ else
+ begin
+ dec(Gear^.WDTimer);
+ Gear^.Timer := 100;
+ end
+ end;
+ end;
+
+ if (Gear^.Tag = sentry_Walking) and ((GameTicks and $1F) = 0) then
+ begin
+ if TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) = 0 then
+ Gear^.X := Gear^.X + SignAs(_1, Gear^.dX)
+ else
+ Gear^.Timer := 0
+ end;
+
+ if ((GameTicks and $1F) = 0) and (Gear^.Tag = sentry_Aiming) then
+ AimSentry(Gear);
+
+ if ((GameTicks and $FF) = 0)
+ and (Gear^.Tag in [sentry_Idle, sentry_Walking])
+ and (CurrentHedgehog <> nil)
+ and (CurrentHedgehog^.Gear <> nil)
+ and ((CurrentHedgehog^.Gear^.State and (gstMoving or gstHHDriven)) = (gstMoving or gstHHDriven)) then
+ begin
+ HHGear := CurrentHedgehog^.Gear;
+ if CheckSentryAttackRange(Gear, HHGear^.X, HHGear^.Y) then
+ begin
+ Gear^.Target.X := hwRound(HHGear^.X);
+ Gear^.Target.Y := hwRound(HHGear^.Y);
+ Gear^.Karma := GameTicks;
+ Gear^.Tag := sentry_Aiming;
+ Gear^.Timer := 1800 + GetRandom(400);
+ end
+ end
end;
procedure doStepSentryDeploy(Gear: PGear);