hijack the duck for an attempted resurrection of the creeper. initial pass.
authornemo
Thu, 02 Aug 2018 20:27:20 -0400
changeset 13605 422d6062620a
parent 13604 73b096e1d895
child 13606 ba6648614cd7
hijack the duck for an attempted resurrection of the creeper. initial pass.
hedgewars/uGears.pas
hedgewars/uGearsHandlersMess.pas
hedgewars/uGearsList.pas
hedgewars/uGearsRender.pas
--- a/hedgewars/uGears.pas	Thu Aug 02 23:43:31 2018 +0200
+++ b/hedgewars/uGears.pas	Thu Aug 02 20:27:20 2018 -0400
@@ -1279,7 +1279,7 @@
             @doStepAddAmmo,
             @doStepGenericFaller,
             @doStepKnife,
-            @doStepDuck,
+            @doStepCreeper,
             @doStepMinigun,
             @doStepMinigunBullet);
 begin
--- a/hedgewars/uGearsHandlersMess.pas	Thu Aug 02 23:43:31 2018 +0200
+++ b/hedgewars/uGearsHandlersMess.pas	Thu Aug 02 20:27:20 2018 -0400
@@ -136,7 +136,7 @@
 procedure doStepIceGun(Gear: PGear);
 procedure doStepAddAmmo(Gear: PGear);
 procedure doStepGenericFaller(Gear: PGear);
-//procedure doStepCreeper(Gear: PGear);
+procedure doStepCreeper(Gear: PGear);
 procedure doStepKnife(Gear: PGear);
 procedure doStepDuck(Gear: PGear);
 procedure doStepMinigunWork(Gear: PGear);
@@ -6506,88 +6506,174 @@
         end;
     end
 end;
-(*
+
 procedure doStepCreeper(Gear: PGear);
-var hogs: PGearArrayS;
-    HHGear: PGear;
-    tdX: hwFloat;
-    dir: LongInt;
+var i,t,targDist,tmpDist: LongWord;
+    targ, tmpG: PGear;
+    trackSpeed, airFriction, tX, tY: hwFloat;
+    isUnderwater: Boolean;
+    vg: PVisualGear;
 begin
-doStepFallingGear(Gear);
-if Gear^.Timer > 0 then dec(Gear^.Timer);
-// creeper sleep phase
-if (Gear^.Hedgehog = nil) and (Gear^.Timer > 0) then exit;
-
-if Gear^.Hedgehog <> nil then HHGear:= Gear^.Hedgehog^.Gear
-else HHGear:= nil;
-
-// creeper boom phase
-if (Gear^.State and gstTmpFlag <> 0) then
-    begin
-    if (Gear^.Timer = 0) then
-        begin
-        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 300, CurrentHedgehog, EXPLAutoSound);
-        DeleteGear(Gear)
-        end;
-    // ssssss he essssscaped
-    if (Gear^.Timer > 250) and ((HHGear = nil) or
-            (((abs(HHGear^.X.Round-Gear^.X.Round) + abs(HHGear^.Y.Round-Gear^.Y.Round) + 2) >  180) and
-            (Distance(HHGear^.X-Gear^.X,HHGear^.Y-Gear^.Y) > _180))) then
-        begin
-        Gear^.State:= Gear^.State and (not gstTmpFlag);
-        Gear^.Timer:= 0
-        end;
-    exit
-    end;
-
-// Search out a new target, as target seek time has expired, target is dead, target is out of range, or we did not have a target
-if (HHGear = nil) or (Gear^.Timer = 0) or
-   (((abs(HHGear^.X.Round-Gear^.X.Round) + abs(HHGear^.Y.Round-Gear^.Y.Round) + 2) >  Gear^.Angle) and
-        (Distance(HHGear^.X-Gear^.X,HHGear^.Y-Gear^.Y) > int2hwFloat(Gear^.Angle)))
-    then
-    begin
-    hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Angle);
-    if hogs.size > 1 then
-        Gear^.Hedgehog:= hogs.ar^[GetRandom(hogs.size)]^.Hedgehog
-    else if hogs.size = 1 then Gear^.Hedgehog:= hogs.ar^[0]^.Hedgehog
-    else Gear^.Hedgehog:= nil;
-    if Gear^.Hedgehog <> nil then Gear^.Timer:= 5000;
-    exit
-    end;
-
-// we have a target. move the creeper.
-if HHGear <> nil then
-    begin
-    // GOTCHA
-    if ((abs(HHGear^.X.Round-Gear^.X.Round) + abs(HHGear^.Y.Round-Gear^.Y.Round) + 2) <  50) and
-         (Distance(HHGear^.X-Gear^.X,HHGear^.Y-Gear^.Y) < _50) then
-        begin
-        // hisssssssssss
-        Gear^.State:= Gear^.State or gstTmpFlag;
-        Gear^.Timer:= 1500;
-        exit
-        end;
-    if (Gear^.State and gstMoving <> 0) then
-        begin
-        Gear^.dY:= _0;
-        Gear^.dX:= _0;
+    doStepFallingGear(Gear);
+	if (Gear^.State and gstFrozen) <> 0 then
+		begin
+		if Gear^.Damage > 0 then
+			begin
+			doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
+			DeleteGear(Gear)
+			end;
+		exit
+		end;
+    if (TurnTimeLeft = 0) or (Gear^.Angle = 0) or (Gear^.Hedgehog = nil) or (Gear^.Hedgehog^.Gear = nil) then
+        begin
+        Gear^.Hedgehog:= nil;
+        targ:= nil;
         end
-    else if (GameTicks and $FF = 0) then
-        begin
-        tdX:= HHGear^.X-Gear^.X;
-        dir:= hwSign(tdX);
-        if TestCollisionX(Gear, dir) = 0 then
-            Gear^.X:= Gear^.X + signAs(_1,tdX);
-        if TestCollisionXwithXYShift(Gear, signAs(_10,tdX), 0, dir) <> 0 then
-            begin
-            Gear^.dX:= SignAs(_0_15, tdX);
-            Gear^.dY:= -_0_3;
-            Gear^.State:= Gear^.State or gstMoving
+    else if Gear^.Hedgehog <> nil then
+        targ:= Gear^.Hedgehog^.Gear;
+    if (targ <> nil) and ((GameTicks and $3F) = 0) and (TestCollisionYKick(Gear, 1) <> 0) then
+        begin
+        vg:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtSmokeWhite);
+        if vg <> nil then vg^.Tint:= $FF0000FF;
+        if (Gear^.X < targ^.X) then // need to add collision checks to avoid walking off edges or getting too close to obstacles where jumping is needed
+            if (WorldEdge = weWrap) and ((targ^.X - Gear^.X) > ((Gear^.X - int2hwFloat(LeftX)) + (int2hwFloat(RightX) - targ^.X))) then
+                 Gear^.dX:= -cLittle
+            else
+                 Gear^.dX:= cLittle
+        else if (Gear^.X > targ^.X) then
+            if (WorldEdge = weWrap) and ((Gear^.X - targ^.X) > ((targ^.X - int2hwFloat(LeftX)) + (int2hwFloat(RightX) - Gear^.X))) then
+                Gear^.dX:= cLittle
+            else
+                Gear^.dX:= -cLittle;
+        if (GetRandom(30) = 0) then
+            begin
+            Gear^.dY := -_0_15;
+            Gear^.dX:= SignAs(_0_15, Gear^.dX);
+            end;
+        MakeHedgehogsStep(Gear);
+        end;
+    if (TurnTimeLeft = 0) and ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) > _0_02.QWordValue) then
+        AllInactive := false;
+
+    if targ <> nil then
+        begin
+        tX:=Gear^.X-targ^.X;
+        tY:=Gear^.Y-targ^.Y;
+        // allow escaping - should maybe flag this too
+        if (GameTicks > Gear^.FlightTime+10000) or 
+            ((tX.Round+tY.Round > Gear^.Angle*6) and
+            (hwRound(hwSqr(tX) + hwSqr(tY)) > sqr(Gear^.Angle*6))) then
+            targ:= nil
+        end;
+
+    // If in ready timer, or after turn, or in first 5 seconds of turn (really a window due to extra time utility)
+    // or mine is inactive due to lack of gsttmpflag or hunting is disabled due to seek radius of 0
+    // then we aren't hunting
+    if (ReadyTimeLeft > 0) or (TurnTimeLeft = 0) or 
+        ((TurnTimeLeft < cHedgehogTurnTime) and (cHedgehogTurnTime-TurnTimeLeft < 5000)) or
+        (Gear^.State and gsttmpFlag = 0) or
+        (Gear^.Angle = 0) then
+        gear^.State:= gear^.State and (not gstChooseTarget)
+    else if
+    // todo, allow not finding new target, set timeout on target retention
+        (Gear^.State and gstAttacking = 0) and
+        ((GameTicks and $FF) = 17) and
+        (GameTicks > Gear^.FlightTime) then // recheck hunted hog
+        begin
+        gear^.State:= gear^.State or gstChooseTarget;
+        if targ <> nil then
+             targDist:= Distance(Gear^.X-targ^.X,Gear^.Y-targ^.Y).Round
+        else targDist:= 0;
+        for t:= 0 to Pred(TeamsCount) do
+            with TeamsArray[t]^ do
+                for i:= 0 to cMaxHHIndex do
+                    if Hedgehogs[i].Gear <> nil then
+                        begin
+                        tmpG:= Hedgehogs[i].Gear;
+                        tX:=Gear^.X-tmpG^.X;
+                        tY:=Gear^.Y-tmpG^.Y;
+                        if (Gear^.Angle = $FFFFFFFF) or
+                            ((tX.Round+tY.Round < Gear^.Angle) and
+                            (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Angle))) then
+                            begin
+                            if targ <> nil then tmpDist:= Distance(tX,tY).Round;
+                            if (targ = nil) or (tmpDist < targDist) then
+                                begin
+                                if targ = nil then targDist:= Distance(tX,tY).Round
+                                else targDist:= tmpDist;
+                                Gear^.Hedgehog:= @Hedgehogs[i];
+                                targ:= tmpG;
+                                end
+                            end
+                        end;
+        if targ <> nil then Gear^.FlightTime:= GameTicks + 5000
+        end;
+
+    if ((Gear^.State and gsttmpFlag) <> 0) and (Gear^.Health <> 0) then
+        begin
+        if ((Gear^.State and gstAttacking) = 0) then
+            begin
+            if ((GameTicks and $1F) = 0) then
+                begin
+                if targ <> nil then
+                    begin
+                    tX:=Gear^.X-targ^.X;
+                    tY:=Gear^.Y-targ^.Y;
+                    if (tX.Round+tY.Round < Gear^.Boom) and
+                       (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then
+                    Gear^.State := Gear^.State or gstAttacking
+                    end
+                else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then
+                    Gear^.State := Gear^.State or gstAttacking
+                end
             end
-        end;
-    end;
+        else // gstAttacking <> 0
+            begin
+            AllInactive := false;
+            if (Gear^.Timer and $1FF) = 0 then
+                PlaySound(sndVaporize);
+            if Gear^.Timer = 0 then
+                begin
+                // recheck
+                if targ <> nil then
+                    begin
+                    tX:=Gear^.X-targ^.X;
+                    tY:=Gear^.Y-targ^.Y;
+                    if (tX.Round+tY.Round < Gear^.Boom) and
+                       (hwRound(hwSqr(tX) + hwSqr(tY)) < sqr(Gear^.Boom)) then
+                        begin
+                        Gear^.Hedgehog:= CurrentHedgehog;
+                        tmpG:= FollowGear;
+                        doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
+                        FollowGear:= tmpG;
+                        DeleteGear(Gear);
+                        exit
+                        end
+                    end
+                else if (Gear^.Angle > 0) and (CheckGearNear(Gear, gtHedgehog, Gear^.Boom, Gear^.Boom) <> nil) then
+                    begin
+                    Gear^.Hedgehog:= CurrentHedgehog;
+                    doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
+                    DeleteGear(Gear);
+                    exit
+                    end;
+                Gear^.State:= Gear^.State and (not gstAttacking);
+                Gear^.Timer:= Gear^.WDTimer
+                end;
+            if Gear^.Timer > 0 then
+                dec(Gear^.Timer);
+            end
+        end
+    else // gsttmpFlag = 0
+        if (TurnTimeLeft = 0)
+        or ((GameFlags and gfInfAttack <> 0) and (GameTicks > Gear^.FlightTime))
+        or (CurrentHedgehog^.Gear = nil) then
+        begin
+        Gear^.FlightTime:= GameTicks;
+        Gear^.State := Gear^.State or gsttmpFlag
+        end
 end;
-*)
+
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepKnife(Gear: PGear);
 //var ox, oy: LongInt;
--- a/hedgewars/uGearsList.pas	Thu Aug 02 23:43:31 2018 +0200
+++ b/hedgewars/uGearsList.pas	Thu Aug 02 20:27:20 2018 -0400
@@ -266,7 +266,7 @@
                     else Gear^.Boom := 3;
     gtPoisonCloud: Gear^.Boom := 20;
           gtKnife: Gear^.Boom := 40000; // arbitrary scaling factor since impact-based
-           gtDuck: Gear^.Boom := 40;
+           gtDuck: Gear^.Boom := 100;
     gtMinigunBullet: Gear^.Boom := 2;
     end;
 
@@ -730,6 +730,7 @@
                 gear^.Density:= _0;
                 end;
         gtDuck: begin
+{
                 gear^.Pos:= 0;               // 0: in air, 1-4: on water, 5-8: underwater
                                              // 1: bottom, 2: bottom (mirrored),
                                              // 3: left Sea edge, 4: right Sea edge
@@ -746,6 +747,25 @@
                 gear^.Friction:= _0_8;
                 gear^.Density:= _0_5;
                 gear^.AdvBounce:= 1;
+}
+
+
+                gear^.Radius:= cHHRadius;
+                gear^.Elasticity:= _0_35;
+                gear^.Friction:= _0_93;
+                gear^.Density:= _5;
+
+                gear^.AdvBounce:= 1;
+                gear^.ImpactSound:= sndAirMineImpact;
+                gear^.nImpactSounds:= 1;
+                gear^.Health:= 30;
+                gear^.Radius:= 8;
+                gear^.Angle:= 175; // Radius at which air bombs will start "seeking". $FFFFFFFF = unlimited. check is skipped.
+                gear^.Power:= cMaxWindSpeed.QWordValue div 2; // hwFloat converted. 1/2 g default. defines the "seek" speed when a gear is in range.
+                gear^.Pos:= cMaxWindSpeed.QWordValue * 3 div 2; // air friction. slows it down when not hitting stuff
+                if gear^.Timer = 0 then
+                    gear^.Timer:= 5000;
+                gear^.WDTimer:= gear^.Timer
                 end;
      gtMinigun: begin
                 // Timer. First, it's the timer before shooting. Then it will become the shooting timer and is set to Karma
--- a/hedgewars/uGearsRender.pas	Thu Aug 02 23:43:31 2018 +0200
+++ b/hedgewars/uGearsRender.pas	Thu Aug 02 20:27:20 2018 -0400
@@ -1604,9 +1604,10 @@
                                 end
                           end
                       end;
-            gtDuck: DrawSpriteRotatedF(sprDuck, x, y, 1, Gear^.Tag, 
-                    // replace with something based on dx/dy?
-                    Gear^.DirAngle + 10-round(20 * abs(1 - (RealTicks mod round(0.1/max(0.00005,cWindSpeedf))) / round(0.05/max(0.00005,cWindSpeedf))) ));
+            gtDuck: if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Gear <> nil) then
+					     DrawSpriteRotatedF(sprDuck, x, y, 1, hwRound(SignAs(_1,Gear^.Hedgehog^.Gear^.X-Gear^.X)), 0) 
+					else DrawSpriteRotatedF(sprDuck, x, y, 1, hwRound(SignAs(_1,Gear^.dX)), 0); 
+
             gtGenericFaller: begin
                              // DEBUG: draw gtGenericFaller
                              if Gear^.Tag <> 0 then