Sorry about the slight delay in pickup. You can blame a few lame cheaters. This is to make their cheating a bit harder.
authornemo
Sat, 14 Jul 2012 23:19:09 -0400
changeset 7389 15c3fb4882df
parent 7388 92535bc7e928
child 7391 588eabb4b384
Sorry about the slight delay in pickup. You can blame a few lame cheaters. This is to make their cheating a bit harder.
hedgewars/GSHandlers.inc
hedgewars/uCommandHandlers.pas
hedgewars/uGears.pas
hedgewars/uGearsHedgehog.pas
hedgewars/uGearsList.pas
hedgewars/uGearsRender.pas
hedgewars/uGearsUtils.pas
hedgewars/uRandom.pas
hedgewars/uTypes.pas
hedgewars/uVariables.pas
--- a/hedgewars/GSHandlers.inc	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/GSHandlers.inc	Sat Jul 14 23:19:09 2012 -0400
@@ -5532,3 +5532,37 @@
         end
     end;
 end;
+
+procedure doStepAddAmmo(Gear: PGear);
+var a: TAmmoType;
+    gi: PGear;
+begin
+if Gear^.Timer > 0 then dec(Gear^.Timer)
+else
+    begin
+    if Gear^.Pos = posCaseUtility then
+        a:= GetUtility(Gear^.Hedgehog)
+    else
+        a:= GetAmmo(Gear^.Hedgehog);
+    CheckSum:= CheckSum xor GameTicks;
+    gi := GearsList;
+    while gi <> nil do
+        begin
+        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;
+        AddRandomness(CheckSum);
+        gi := gi^.NextGear
+        end;
+    AddPickup(Gear^.Hedgehog^, a, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
+    DeleteGear(Gear)
+    end;
+end;
+
+procedure doStepGenericFaller(Gear: PGear);
+begin
+if Gear^.Timer > 0 then 
+    begin
+    doStepFallingGear(Gear);
+    dec(Gear^.Timer)
+    end
+else DeleteGear(Gear)
+end;
--- a/hedgewars/uCommandHandlers.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uCommandHandlers.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -412,18 +412,19 @@
 end;
 
 procedure chNextTurn(var s: shortstring);
-var checksum: Longword;
+var i: Longword;
     gi: PGear;
 begin
     s:= s; // avoid compiler hint
 
     TryDo(AllInactive, '/nextturn called when not all gears are inactive', true);
 
-    checksum:= GameTicks;
+    CheckSum:= CheckSum xor GameTicks;
     gi := GearsList;
     while gi <> nil do
         begin
-        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;
+        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;
+        AddRandomness(CheckSum);
         gi := gi^.NextGear
         end;
 
@@ -431,11 +432,11 @@
         begin
         s[0]:= #5;
         s[1]:= 'N';
-        SDLNet_Write32(checksum, @s[2]);
+        SDLNet_Write32(CheckSum, @s[2]);
         SendIPC(s)
         end
     else
-        TryDo(checksum = lastTurnChecksum, 'Desync detected', true);
+        TryDo(CheckSum = lastTurnChecksum, 'Desync detected', true);
     AddFileLog('Next turn: time '+inttostr(GameTicks));
 end;
 
--- a/hedgewars/uGears.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uGears.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -1313,7 +1313,9 @@
             @doStepStructure,
             @doStepLandGun,
             @doStepTardis,
-            @doStepIceGun);
+            @doStepIceGun,
+            @doStepAddAmmo,
+            @doStepGenericFaller);
 begin
     doStepHandlers:= handlers;
 
--- a/hedgewars/uGearsHedgehog.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uGearsHedgehog.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -28,6 +28,7 @@
 procedure doStepHedgehogMoving(Gear: PGear); 
 procedure HedgehogChAngle(HHGear: PGear); 
 procedure PickUp(HH, Gear: PGear);
+procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
 
 implementation
 uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, 
@@ -565,15 +566,41 @@
     end
 end;
 
+procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord);
+var s: shortstring;
+    vga: PVisualGear;
+begin
+    PlaySound(sndShotgunReload);
+    if cnt <> 0 then AddAmmo(HH, ammo, cnt)
+    else AddAmmo(HH, ammo);
+
+    if (not (HH.Team^.ExtDriven 
+    or (HH.BotLevel > 0)))
+    or (HH.Team^.Clan^.ClanIndex = LocalClan)
+    or (GameType = gmtDemo)  then
+        begin
+        if cnt <> 0 then
+            s:= trammo[Ammoz[ammo].NameId] + ' (+' + IntToStr(cnt) + ')'
+        else
+            s:= trammo[Ammoz[ammo].NameId] + ' (+' + IntToStr(Ammoz[ammo].NumberInCase) + ')';
+        AddCaption(s, HH.Team^.Clan^.Color, capgrpAmmoinfo);
+
+        // show ammo icon
+        vga:= AddVisualGear(X, Y, vgtAmmo);
+        if vga <> nil then
+            vga^.Frame:= Longword(ammo);
+        end;
+end;
+
 ////////////////////////////////////////////////////////////////////////////////
 procedure PickUp(HH, Gear: PGear);
 var s: shortstring;
     a: TAmmoType;
     i: LongInt;
     vga: PVisualGear;
+    ag: PGear;
 begin
 Gear^.Message:= gmDestroy;
-PlaySound(sndShotgunReload);
 if (Gear^.Pos and posCaseExplode) <> 0 then
     if (Gear^.Pos and posCasePoison) <> 0 then
         doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 25, HH^.Hedgehog, EXPLAutoSound + EXPLPoisoned)
@@ -585,39 +612,24 @@
 case Gear^.Pos of
        posCaseUtility,
        posCaseAmmo: begin
-                    if Gear^.AmmoType <> amNothing then a:= Gear^.AmmoType 
+                    if Gear^.AmmoType <> amNothing then 
+                        begin
+                        AddPickup(HH^.Hedgehog^, Gear^.AmmoType, Gear^.Power, hwRound(Gear^.X), hwRound(Gear^.Y));
+                        end
                     else
                         begin
-                        for i:= 0 to GameTicks and $7F do
-                            GetRandom(2); // Burn some random numbers
-                        if Gear^.Pos = posCaseUtility then
-                            a:= GetUtility(HH^.Hedgehog)
-                        else
-                            a:= GetAmmo(HH^.Hedgehog)
+// Add spawning here...
+                        AddRandomness(CheckSum xor GameTicks);
+                        for i:= 0 to GetRandom(50)+50 do
+                            AddGear(GetRandom(rightX-leftX)+leftX, GetRandom(LAND_HEIGHT-topY)+topY, gtGenericFaller,
+                                    gstInvisible, _90-(GetRandomf*_360), _90-(GetRandomf*_360), GetRandom(500));
+                        ag:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtAddAmmo, gstInvisible, _0, _0, GetRandom(200)+100);
+                        ag^.Pos:= Gear^.Pos;
+                        ag^.Power:= Gear^.Power
                         end;
-                    if Gear^.Power <> 0 then AddAmmo(HH^.Hedgehog^, a, Gear^.Power)
-                    else AddAmmo(HH^.Hedgehog^, a);
-// Possibly needs to check shared clan ammo game flag once added.
-// On the other hand, no obvious reason that clan members shouldn't know what ammo another clan member picked up
-                    if (not (HH^.Hedgehog^.Team^.ExtDriven 
-                    or (HH^.Hedgehog^.BotLevel > 0)))
-                    or (HH^.Hedgehog^.Team^.Clan^.ClanIndex = LocalClan)
-                    or (GameType = gmtDemo)  then
-                        begin
-                        if Gear^.Power <> 0 then
-                            s:= trammo[Ammoz[a].NameId] + ' (+' + IntToStr(Gear^.Power) + ')'
-                        else
-                            s:= trammo[Ammoz[a].NameId] + ' (+' + IntToStr(Ammoz[a].NumberInCase) + ')';
-                        AddCaption(s, HH^.Hedgehog^.Team^.Clan^.Color, capgrpAmmoinfo);
-
-                        // show ammo icon
-                        vga:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtAmmo);
-                        if vga <> nil then
-                            vga^.Frame:= Longword(a);
-                        end;
-
                     end;
      posCaseHealth: begin
+                    PlaySound(sndShotgunReload);
                     inc(HH^.Health, Gear^.Health);
                     HH^.Hedgehog^.Effects[hePoisoned] := 0;
                     str(Gear^.Health, s);
@@ -1224,6 +1236,7 @@
     land: Word; *)
 var slope: hwFloat; 
 begin
+CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
 if (Gear^.Message and gmDestroy) <> 0 then
     begin
     DeleteGear(Gear);
--- a/hedgewars/uGearsList.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uGearsList.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -460,6 +460,13 @@
                 gear^.Pos:= 1;
                 end;
       gtIceGun: gear^.Health:= 1000;
+gtGenericFaller:begin
+                gear^.AdvBounce:= 1;
+                gear^.Radius:= 1;
+                gear^.Elasticity:= _0_9;
+                gear^.Friction:= _0_995;
+                gear^.Density:= _1;
+                end;
     end;
 
 InsertGearToList(gear);
@@ -557,8 +564,10 @@
                 end
         end;
 with Gear^ do
+    begin
     AddFileLog('Delete: #' + inttostr(uid) + ' (' + inttostr(hwRound(x)) + ',' + inttostr(hwRound(y)) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
-
+    AddRandomness(X.round xor X.frac xor dX.round xor dX.frac xor Y.round xor Y.frac xor dY.round xor dY.frac)
+    end;
 if CurAmmoGear = Gear then
     CurAmmoGear:= nil;
 if FollowGear = Gear then
--- a/hedgewars/uGearsRender.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uGearsRender.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -21,7 +21,7 @@
 unit uGearsRender;
 
 interface
-uses uTypes, uConsts, GLunit, uFloat, SDLh;
+uses uTypes, uConsts, GLunit, uFloat, SDLh, uRandom;
 
 procedure RenderGear(Gear: PGear; x, y: LongInt);
 
@@ -287,6 +287,7 @@
             dy:= -Cos(Gear^.Angle * pi / cMaxAngle);
             if cLaserSighting then
                 begin
+                GetRandom(2); // no, this does not prevent it, just makes things harder
                 lx:= GetLaunchX(HH^.CurAmmoType, sign * m, Gear^.Angle);
                 ly:= GetLaunchY(HH^.CurAmmoType, Gear^.Angle);
 
@@ -1213,9 +1214,8 @@
                                 else DrawLine(hwRound(HHGear^.X), hwRound(HHGear^.Y), hwRound(Gear^.X), hwRound(Gear^.Y), 4.0, i, i, $FF, $40);
                                 end
                           end
-                      end
-
-
+                      end;
+            gtGenericFaller: DrawCircle(x, y, 3, 3, $FF, $00, $00, $FF);  // debug
          end;
       if Gear^.RenderTimer and (Gear^.Tex <> nil) then
           DrawTextureCentered(x + 8, y + 8, Gear^.Tex);
--- a/hedgewars/uGearsUtils.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uGearsUtils.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -343,6 +343,11 @@
     Y:= hwRound(Gear^.Y);
     if cWaterLine < Y + Gear^.Radius then
         begin
+        if Gear^.State and gstInvisible <> 0 then
+            begin
+            DeleteGear(Gear);
+            exit
+            end;
         isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
         skipSpeed := _0_25;
         skipAngle := _1_9;
--- a/hedgewars/uRandom.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uRandom.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -35,15 +35,23 @@
 
 procedure SetRandomSeed(Seed: shortstring); // Sets the seed that should be used for generating pseudo-random values.
 function  GetRandomf: hwFloat; overload; // Returns a pseudo-random hwFloat.
-function  GetRandom(m: LongWord): LongWord; overload; // Returns a positive pseudo-random integer smaller than m.
+function  GetRandom(m: LongWord): LongWord; overload; inline; // Returns a positive pseudo-random integer smaller than m.
+procedure AddRandomness(r: LongWord); inline;
 function  rndSign(num: hwFloat): hwFloat; // Returns num with a random chance of having a inverted sign.
 
+
 implementation
 
 var cirbuf: array[0..63] of Longword;
     n: byte;
 
-function GetNext: Longword;
+procedure AddRandomness(r: LongWord); inline;
+begin
+n:= (n + 1) and $3F;
+cirbuf[n]:= cirbuf[n] xor r
+end;
+
+function GetNext: Longword; inline;
 begin
 n:= (n + 1) and $3F;
 cirbuf[n]:=
@@ -79,7 +87,7 @@
 GetRandomf.QWordValue:= GetNext
 end;
 
-function GetRandom(m: LongWord): LongWord;
+function GetRandom(m: LongWord): LongWord; inline;
 begin
 GetNext;
 GetRandom:= GetNext mod m
--- a/hedgewars/uTypes.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uTypes.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -102,7 +102,7 @@
             gtSniperRifleShot, gtJetpack, gtMolotov, gtBirdy, // 44
             gtEgg, gtPortal, gtPiano, gtGasBomb, gtSineGunShot, gtFlamethrower, // 50
             gtSMine, gtPoisonCloud, gtHammer, gtHammerHit, gtResurrector, // 55
-            gtNapalmBomb, gtSnowball, gtFlake, gtStructure, gtLandGun, gtTardis, gtIceGun); // 62
+            gtNapalmBomb, gtSnowball, gtFlake, gtStructure, gtLandGun, gtTardis, gtIceGun, gtAddAmmo, gtGenericFaller); // 62
 
     // Gears that are _only_ of visual nature (e.g. background stuff, visual effects, speechbubbles, etc.)
     TVisualGearType = (vgtFlake, vgtCloud, vgtExplPart, vgtExplPart2, vgtFire,
@@ -340,6 +340,8 @@
             HatTex: PTexture;
             Ammo: PHHAmmo;
             CurAmmoType: TAmmoType;
+            PickUpType: LongWord;
+            PickUpDelay: LongInt;
             AmmoStore: Longword;
             Team: PTeam;
             MultiShootAttacks: Longword;
--- a/hedgewars/uVariables.pas	Fri Jul 13 13:21:52 2012 +0400
+++ b/hedgewars/uVariables.pas	Sat Jul 14 23:19:09 2012 -0400
@@ -64,6 +64,7 @@
     fastUntilLag    : boolean;
     autoCameraOn    : boolean;
 
+    CheckSum        : LongWord;
     GameTicks       : LongWord;
     GameState       : TGameState;
     GameType        : TGameType;
@@ -2368,6 +2369,8 @@
 (*        gtLandGun *) , amLandGun
 (*         gtTardis *) , amTardis
 (*         gtIceGun *) , amIceGun
+(*        gtAddAmmo *) , amNothing
+(*  gtGenericFaller *) , amNothing
     );
 
 var
@@ -2530,6 +2533,7 @@
     CursorMovementX     := 0;
     CursorMovementY     := 0;
     GameTicks           := 0;
+    CheckSum            := 0;
     cWaterLine          := LAND_HEIGHT;
     cGearScrEdgesDist   := 240;