Add gear gtDuck: rubber duck
Properties:
- Falls straight down
- Swims on water and follows wind direction
- Follows Sea world edge
- Explodes on collision or after 9s
- Timer resets when hitting water
--- a/hedgewars/uGears.pas Sat Apr 08 18:26:25 2017 +0200
+++ b/hedgewars/uGears.pas Sat Apr 08 18:36:12 2017 +0200
@@ -1224,7 +1224,8 @@
@doStepIceGun,
@doStepAddAmmo,
@doStepGenericFaller,
- @doStepKnife);
+ @doStepKnife,
+ @doStepDuck);
begin
doStepHandlers:= handlers;
--- a/hedgewars/uGearsHandlersMess.pas Sat Apr 08 18:26:25 2017 +0200
+++ b/hedgewars/uGearsHandlersMess.pas Sat Apr 08 18:36:12 2017 +0200
@@ -138,6 +138,7 @@
procedure doStepGenericFaller(Gear: PGear);
//procedure doStepCreeper(Gear: PGear);
procedure doStepKnife(Gear: PGear);
+procedure doStepDuck(Gear: PGear);
var
upd: Longword;
@@ -6345,6 +6346,89 @@
and (TestCollisionYwithGear(Gear, 1) = 0) then Gear^.State:= Gear^.State and (not gstCollision) or gstMoving;
end
end;
+
+////////////////////////////////////////////////////////////////////////////////
+procedure doStepDuck(Gear: PGear);
+begin
+ // Mirror duck on bounce world edge, even turn around later
+ if WorldWrap(Gear) and (WorldEdge = weBounce) then
+ begin
+ Gear^.Tag:= Gear^.Tag * -1;
+ if Gear^.Pos = 2 then
+ Gear^.Pos:= 1
+ else if Gear^.Pos = 1 then
+ Gear^.Pos:= 2;
+ end;
+
+ AllInactive := false;
+
+ // Duck falls (Pos = 0)
+ if Gear^.Pos = 0 then
+ begin
+ doStepFallingGear(Gear);
+ // Karma is distance from water
+ if cWaterLine <= hwRound(Gear^.Y) + Gear^.Karma then
+ begin
+ Gear^.Pos:= 1;
+ Gear^.Timer:= Gear^.WDTimer;
+ Gear^.dY:= _0;
+ Gear^.State:= Gear^.State or gstNoGravity;
+ end;
+ end
+
+ // Manual speed handling when duck is on water (Pos <> 0)
+ else
+ begin
+ Gear^.X:= Gear^.X + Gear^.dX;
+ Gear^.Y:= Gear^.Y + Gear^.dY;
+ end;
+
+ // Mirrored duck
+ // Pos 1 or 2: Duck is on water (not Sea world edge)
+ if Gear^.Pos = 1 then
+ Gear^.dX:= cWindSpeed * 500
+ else if Gear^.Pos = 2 then
+ Gear^.dX:= -cWindSpeed * 500;
+
+ // Rotate duck and change direction when reaching Sea world edge (Pos 3 or 4)
+ if WorldEdge = weSea then
+ begin
+ // Left edge
+ if (LeftX >= hwRound(Gear^.X) - Gear^.Karma) and (Gear^.Pos < 3) then
+ begin
+ Gear^.Pos:= 3;
+ if Gear^.Tag = 1 then
+ Gear^.Angle:= 90
+ else
+ Gear^.Angle:= 270;
+ Gear^.dY:= Gear^.dX;
+ Gear^.dX:= _0;
+ end
+ // Right edge
+ else if (RightX <= hwRound(Gear^.X) + Gear^.Karma) and (Gear^.Pos < 3) then
+ begin
+ Gear^.Pos:= 4;
+ if Gear^.Tag = 1 then
+ Gear^.Angle:= 270
+ else
+ Gear^.Angle:= 90;
+ Gear^.dY:= -Gear^.dX;
+ Gear^.dX:= _0;
+ end;
+ end;
+
+ // Explode duck
+ CheckCollision(Gear);
+ if (Gear^.Timer = 0) or ((Gear^.State and gstCollision) <> 0) then
+ begin
+ doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), Gear^.Boom, Gear^.Hedgehog, EXPLAutoSound);
+ DeleteGear(Gear);
+ exit;
+ end;
+
+ dec(Gear^.Timer);
+end;
+
(*
This didn't end up getting used, but, who knows, might be reasonable for javellin or something
// Make the knife initial angle based on the hog attack angle, or is that too hard?
--- a/hedgewars/uGearsList.pas Sat Apr 08 18:26:25 2017 +0200
+++ b/hedgewars/uGearsList.pas Sat Apr 08 18:36:12 2017 +0200
@@ -105,6 +105,7 @@
(* gtAddAmmo *) , amNothing
(* gtGenericFaller *) , amNothing
(* gtKnife *) , amKnife
+(* gtDuck *) , amNothing // TODO: Add ammo type
);
@@ -263,6 +264,7 @@
else Gear^.Boom := 3;
gtPoisonCloud: Gear^.Boom := 20;
gtKnife: Gear^.Boom := 40000; // arbitrary scaling factor since impact-based
+ gtDuck: Gear^.Boom := 40;
end;
case Kind of
@@ -717,6 +719,19 @@
gear^.Health:= 1000;
gear^.Radius:= 8;
end;
+ gtDuck: begin
+ gear^.Pos:= 0; // 0: falling/in air, 1-4: on water
+ gear^.Tag:= 1; // 1: facing right, -1: facing left
+ if gear^.Timer = 0 then
+ gear^.Timer:= 9000; // Explosion timer to avoid duck existing forever
+ gear^.WDTimer:= gear^.Timer; // For restoring the timer, timer is reset when hitting water
+ gear^.Radius:= 9; // Collision radius (with landscape)
+ gear^.Karma:= 24; // Distance from water when swimming
+ gear^.Elasticity:= _0_6;
+ gear^.Friction:= _0_03;
+ gear^.Density:= _0_5;
+ gear^.AdvBounce:= 1;
+ end;
gtGenericFaller:begin
gear^.AdvBounce:= 1;
gear^.Radius:= 1;
--- a/hedgewars/uGearsRender.pas Sat Apr 08 18:26:25 2017 +0200
+++ b/hedgewars/uGearsRender.pas Sat Apr 08 18:36:12 2017 +0200
@@ -1325,7 +1325,7 @@
end;
gtDynamite: begin
DrawSprite(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
- if (random(3) = 0) and ((Gear^.State and gstDrowning) = 0) then
+ if (random(3) = 0) then
begin
vg:= AddVisualGear(hwRound(Gear^.X)+12-(Gear^.Tag shr 1), hwRound(Gear^.Y)-16, vgtStraightShot);
if vg <> nil then
@@ -1528,6 +1528,7 @@
end
end
end;
+ gtDuck: DrawSpriteRotatedF(sprDuck, x, y, 1, Gear^.Tag, Gear^.Angle);
gtGenericFaller: DrawCircle(x, y, 3, 3, $FF, $00, $00, $FF); // debug
end;
if Gear^.RenderTimer and (Gear^.Tex <> nil) then
--- a/hedgewars/uTypes.pas Sat Apr 08 18:26:25 2017 +0200
+++ b/hedgewars/uTypes.pas Sat Apr 08 18:36:12 2017 +0200
@@ -90,7 +90,7 @@
sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis,
sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun,
sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine, sprHandAirMine,
- sprFlakeL, sprSDFlakeL, sprCloudL, sprSDCloudL
+ sprFlakeL, sprSDFlakeL, sprCloudL, sprSDCloudL, sprDuck
);
// Gears that interact with other Gears and/or Land
@@ -108,7 +108,7 @@
gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 51
gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 56
gtNapalmBomb, gtSnowball, gtFlake, {gtStructure,} gtLandGun, gtTardis, // 61
- gtIceGun, gtAddAmmo, gtGenericFaller, gtKnife); // 65
+ gtIceGun, gtAddAmmo, gtGenericFaller, gtKnife, gtDuck); // 66
// Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -454,7 +454,8 @@
sidMolotov, sidBirdy, sidPortalGun, sidPiano, sidGasBomb,
sidSineGun, sidFlamethrower,sidSMine, sidHammer, sidResurrector,
sidDrillStrike, sidSnowball, sidNothing, sidTardis,
- {sidStructure,} sidLandGun, sidIceGun, sidKnife, sidRubber, sidAirMine);
+ {sidStructure,} sidLandGun, sidIceGun, sidKnife, sidRubber, sidAirMine,
+ sidDuck);
TMsgStrId = (sidLoading, sidDraw, sidWinner, sidVolume, sidPaused,
sidConfirm, sidSuddenDeath, sidRemaining, sidFuel, sidSync,
--- a/hedgewars/uVariables.pas Sat Apr 08 18:26:25 2017 +0200
+++ b/hedgewars/uVariables.pas Sat Apr 08 18:36:12 2017 +0200
@@ -746,7 +746,9 @@
(FileName: 'CloudsL'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloudL
(FileName: 'SDCloudsL'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true)// sprSDCloudL
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprSDCloudL
+ (FileName: 'Duck'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true) // sprDuck
);
const