hedgewars/uGearsHedgehog.pas
branchwebgl
changeset 9950 2759212a27de
parent 9521 8054d9d775fd
parent 9917 1ca194a8b509
child 9954 bf51bc7e2808
--- a/hedgewars/uGearsHedgehog.pas	Fri Oct 11 17:43:13 2013 +0200
+++ b/hedgewars/uGearsHedgehog.pas	Sat Jan 04 23:55:54 2014 +0400
@@ -20,7 +20,7 @@
 
 unit uGearsHedgehog;
 interface
-uses uTypes;
+uses uTypes, uGearsHandlersMess; 
 
 procedure doStepHedgehog(Gear: PGear);
 procedure AfterAttack;
@@ -35,10 +35,22 @@
 uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions,
     uCommands, uLocale, uUtils, uStats, uIO, uScript,
     uGearsList, uCollisions, uRandom, uStore, uTeams,
-    uGearsUtils, uVisualGearsList;
+    uGearsUtils, uVisualGearsList, uChat;
 
 var GHStepTicks: LongWord = 0;
 
+procedure AFKSkip;
+var
+    t: byte;
+begin
+    t:= 0;
+    while (TeamsArray[t] <> CurrentTeam) do inc(t);
+
+    SendHogSpeech(#1 + char(t) + 'AFK');
+
+    ParseCommand('/skip', true)
+end;
+
 // Shouldn't more of this ammo switching stuff be moved to uAmmos ?
 function ChangeAmmo(HHGear: PGear): boolean;
 var slot, i: Longword;
@@ -53,7 +65,7 @@
     HHGear^.Message:= HHGear^.Message and (not gmSlot);
     prevAmmo:= CurAmmoType;
     ammoidx:= 0;
-    if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0)
+    if (((HHGear^.State and (gstAttacking or gstAttacked)) <> 0) and (GameFlags and gfInfAttack = 0))
     or ((HHGear^.State and gstHHDriven) = 0) then
         exit;
     ChangeAmmo:= true;
@@ -114,9 +126,9 @@
             LoadHedgehogHat(HHGear^.Hedgehog^, Hat);
         end;
     // Try again in the next slot
-    if CurAmmoType = prevAmmo then
+    if (CurAmmoType = prevAmmo) and (slot < cMaxSlotIndex) then 
         begin
-        if slot >= cMaxSlotIndex then slot:= 0 else inc(slot);
+        inc(slot);
         HHGear^.MsgParam:= slot;
         ChangeAmmo(HHGear)
         end
@@ -128,6 +140,7 @@
     weap: TAmmoType;
     Hedgehog: PHedgehog;
     s: boolean;
+    prevState, newState: LongWord;
 begin
 s:= false;
 
@@ -143,12 +156,18 @@
 
 HHGear^.Message:= HHGear^.Message and (not gmWeapon);
 
+prevState:= HHGear^.State;
+newState:= prevState;
 with Hedgehog^ do
     while (CurAmmoType <> weap) and (t >= 0) do
         begin
         s:= ChangeAmmo(HHGear);
+        if HHGear^.State <> prevState then // so we can keep gstAttacked out of consideration when looping
+            newState:= HHGear^.State;
+        HHGear^.State:= prevState;
         dec(t)
         end;
+HHGear^.State:= newState;
 
 if s then
     ApplyAmmoChanges(HHGear^.Hedgehog^)
@@ -334,6 +353,10 @@
                        amNapalm: newGear:= AddGear(CurWeapon^.Pos, 0, gtAirAttack, 2, _0, _0, 0);
                     amBlowTorch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtBlowTorch, 0, SignAs(_0_5, dX), _0, 0);
                        amGirder: newGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+                       amRubber: begin
+                                 newGear:= AddGear(0, 0, gtGirder, CurWeapon^.Pos, _0, _0, 0);
+                                 newGear^.AmmoType:= amRubber
+                                 end;
                      amTeleport: newGear:= AddGear(CurWeapon^.Pos, 0, gtTeleport, 0, _0, _0, 0);
                        amSwitch: newGear:= AddGear(hwRound(lx), hwRound(ly), gtSwitcher, 0, _0, _0, 0);
                        amMortar: begin
@@ -365,7 +388,7 @@
                                  PlaySound(sndHellishImpact4);
                                  cDamageModifier:= _1_5
                                  end;
-                 amInvulnerable: Invulnerable:= true;
+                 amInvulnerable: Effects[heInvulnerable]:= 1;
                     amExtraTime: begin
                                  PlaySound(sndSwitchHog);
                                  TurnTimeLeft:= TurnTimeLeft + 30000
@@ -390,7 +413,7 @@
                                  newGear^.SoundChannel := LoopSound(sndResurrector);
                                  end;
                     //amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000);
-                       amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000);
+                       amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 0);
                        amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0);
             end;
             if altUse and (newGear <> nil) and 
@@ -425,7 +448,7 @@
                 amFlamethrower, amLandGun,
                  amResurrector, //amStructure,
                       amTardis, amPiano,
-                      amIceGun: CurAmmoGear:= newGear;
+                      amIceGun, amRubber: CurAmmoGear:= newGear;
             end;
 
             if ((CurAmmoType = amMine) or (CurAmmoType = amSMine)) and (GameFlags and gfInfAttack <> 0) then
@@ -747,13 +770,13 @@
         Gear^.Message:= Gear^.Message and (not gmLJump);
         DeleteCI(Gear);
         if TestCollisionYwithGear(Gear, -1) = 0 then
-            if not TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) then
+            if TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) = 0 then
                 Gear^.Y:= Gear^.Y - _2
             else
-                if not TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) then
+                if TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) = 0 then
                     Gear^.Y:= Gear^.Y - _1;
-            if not (TestCollisionXwithGear(Gear, hwSign(Gear^.dX))
-            or   (TestCollisionYwithGear(Gear, -1) <> 0)) then
+            if (TestCollisionXwithGear(Gear, hwSign(Gear^.dX)) = 0) and
+               (TestCollisionYwithGear(Gear, -1) = 0) then
                 begin
                 Gear^.dY:= -_0_15;
                 if not cArtillery then
@@ -841,11 +864,21 @@
     Gear^.State:= Gear^.State and (not gstMoving);
     exit
     end;
-isFalling:= (Gear^.dY.isNegative) or (not TestCollisionYKick(Gear, 1));
+isFalling:= (Gear^.dY.isNegative) or (TestCollisionYKick(Gear, 1) = 0);
 if isFalling then
     begin
-    if (Gear^.dY.isNegative) and TestCollisionYKick(Gear, -1) then
-        Gear^.dY:= _0;
+    land:= TestCollisionYKick(Gear, -1);
+    if (Gear^.dY.isNegative) and (land <> 0) then
+        begin
+        if land and lfBouncy <> 0 then
+            begin
+            doStepFallingGear(Gear);
+            Gear^.dX:= Gear^.dX * _0_8
+            end;
+        if (land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0) then
+            Gear^.dY:= _0;
+        Gear^.State:= Gear^.State and not gstCollision 
+        end;
     Gear^.State:= Gear^.State or gstMoving;
     if (CurrentHedgehog^.Gear = Gear) and (CurrentHedgehog^.Gear^.State and gstHHDriven <> 0) and
        (not CurrentTeam^.ExtDriven) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then
@@ -870,19 +903,36 @@
 else
     begin
     land:= TestCollisionYwithGear(Gear, 1);
-    if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0)
+    if ((Gear^.dX.QWordValue + Gear^.dY.QWordValue) < _0_55.QWordValue) and ((land and lfIce) = 0) 
+    and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0)) 
     and ((Gear^.State and gstHHJumping) <> 0) then
         SetLittle(Gear^.dX);
 
     if not Gear^.dY.isNegative then
         begin
+        if land and lfBouncy <> 0 then
+            begin
+            doStepFallingGear(Gear);
+            // hogs for some reason have very low friction. slippery little buggers
+            Gear^.dX:= Gear^.dX * _0_8
+            end;
+
         CheckHHDamage(Gear);
 
-        if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery)
-        and (Gear^.dX.QWordValue < _0_02.QWordValue) then
-            Gear^.dX.isNegative:= not Gear^.dX.isNegative; // landing after high jump
-        Gear^.State:= Gear^.State and (not (gstHHJumping or gstHHHJump));
-        Gear^.dY:= _0;
+        if (land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0) then
+            begin
+            if ((Gear^.State and gstHHHJump) <> 0) and (not cArtillery)
+            and (Gear^.dX.QWordValue < _0_02.QWordValue) then
+                begin
+                if land and lfBouncy <> 0 then
+                    Gear^.dY:= _0;
+                Gear^.dX.isNegative:= not Gear^.dX.isNegative // landing after high jump
+                end;
+            Gear^.State:= Gear^.State and (not (gstHHJumping or gstHHHJump));
+            if (land and lfBouncy = 0) or (Gear^.dX.QWordValue < _0_02.QWordValue) then
+                Gear^.dY:= _0
+            end;
+        Gear^.State:= Gear^.State and not gstCollision 
         end
     else
         Gear^.dY:= Gear^.dY + cGravity;
@@ -908,43 +958,43 @@
    end;
 
 if (Gear^.State and gstMoving) <> 0 then
-    if TestCollisionXKick(Gear, hwSign(Gear^.dX)) then
+    if TestCollisionXKick(Gear, hwSign(Gear^.dX)) <> 0 then
         if not isFalling then
             if hwAbs(Gear^.dX) > _0_01 then
-                if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -1, hwSign(Gear^.dX)) or
-                (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+                if  (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -1, hwSign(Gear^.dX)) = 0) and
+                    (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
                     begin
                     Gear^.X:= Gear^.X + Gear^.dX;
                     Gear^.dX:= Gear^.dX * _0_96;
                     Gear^.Y:= Gear^.Y - _1
                     end
                 else
-                    if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -2, hwSign(Gear^.dX)) or
-                        (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+                    if  (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -2, hwSign(Gear^.dX)) = 0) and
+                        (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
                         begin
                         Gear^.X:= Gear^.X + Gear^.dX;
                         Gear^.dX:= Gear^.dX * _0_93;
                         Gear^.Y:= Gear^.Y - _2
                         end
                     else
-                    if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -3, hwSign(Gear^.dX)) or
-                        (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+                    if  (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -3, hwSign(Gear^.dX)) = 0) and
+                        (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
                         begin
                         Gear^.X:= Gear^.X + Gear^.dX;
                         Gear^.dX:= Gear^.dX * _0_9 ;
                         Gear^.Y:= Gear^.Y - _3
                         end
                     else
-                        if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -4, hwSign(Gear^.dX)) or
-                        (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+                        if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -4, hwSign(Gear^.dX)) = 0) and
+                           (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
                             begin
                             Gear^.X:= Gear^.X + Gear^.dX;
                             Gear^.dX:= Gear^.dX * _0_87;
                             Gear^.Y:= Gear^.Y - _4
                             end
                     else
-                        if not (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -5, hwSign(Gear^.dX)) or
-                        (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1))) then
+                        if (TestCollisionXwithXYShift(Gear, int2hwFloat(hwSign(Gear^.dX)) - Gear^.dX, -5, hwSign(Gear^.dX)) = 0) and
+                           (TestCollisionYwithXYShift(Gear, hwSign(Gear^.dX) - hwRound(Gear^.dX), -1, -1) = 0) then
                             begin
                             Gear^.X:= Gear^.X + Gear^.dX;
                             Gear^.dX:= Gear^.dX * _0_84;
@@ -978,7 +1028,7 @@
     begin
     Gear^.State:= Gear^.State and (not gstWinner);
     Gear^.State:= Gear^.State and (not gstMoving);
-    while (TestCollisionYWithGear(Gear,1) = 0) and (not CheckGearDrowning(Gear)) and (Gear <> nil) do
+    while (not CheckGearDrowning(Gear)) and (Gear <> nil) and (TestCollisionYWithGear(Gear,1) = 0) do
         Gear^.Y:= Gear^.Y + _1;
 
     // could become nil in CheckGearDrowning if ai's hog fails to respawn in ai survival
@@ -995,15 +1045,21 @@
 // ARTILLERY but not being moved by explosions
     Gear^.X:= Gear^.X + Gear^.dX;
     Gear^.Y:= Gear^.Y + Gear^.dY;
-    if (not Gear^.dY.isNegative) and (not TestCollisionYKick(Gear, 1))
-    and TestCollisionYwithXYShift(Gear, 0, 1, 1) then
+    if (not Gear^.dY.isNegative) and (TestCollisionYKick(Gear, 1) = 0) then
         begin
-        CheckHHDamage(Gear);
-        Gear^.dY:= _0;
-        Gear^.Y:= Gear^.Y + _1
+        land:= TestCollisionYwithXYShift(Gear, 0, 1, 1);
+        if land and lfBouncy <> 0 then
+            doStepFallingGear(Gear);
+
+        if (land <> 0) and ((land and lfBouncy = 0) or (Gear^.State and gstCollision <> 0)) then
+            begin
+            CheckHHDamage(Gear);
+            Gear^.dY:= _0;
+            Gear^.Y:= Gear^.Y + _1
+            end;
+        Gear^.State:= Gear^.State and not gstCollision 
         end;
 
-    CheckGearDrowning(Gear);
     // could become nil if ai's hog fails to respawn in ai survival
     if Gear = nil then exit;
     // hide target cursor if current hog is drowning
@@ -1060,6 +1116,12 @@
     exit
     end;
 
+if isAFK and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0) then
+    begin
+    AFKSkip;
+    exit
+    end;
+
 if (HHGear^.State and gstAnimation) <> 0 then
     begin
     HHGear^.Message:= 0;
@@ -1143,7 +1205,7 @@
 
     HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump));
 
-    if (not cArtillery) and wasJumping and TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) then
+    if (not cArtillery) and wasJumping and (TestCollisionXwithGear(HHGear, hwSign(HHGear^.dX)) <> 0) then
         SetLittle(HHGear^.dX);
 
     if Hedgehog^.Gear <> nil then
@@ -1252,7 +1314,7 @@
     if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0)
     and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0)
     and ((Gear^.Hedgehog = nil) or ((Gear^.Hedgehog^.Effects[heFrozen] = 0) or (Gear^.Hedgehog^.Effects[heFrozen] > 255)))
-    and (not Gear^.dY.isNegative) and (TurnTimeLeft > 0) and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
+    and (not Gear^.dY.isNegative) and TurnClockActive and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then
         begin
         slope:= CalcSlopeBelowGear(Gear);
         if slope.QWordValue > 730144440 then // ignore mild slopes
@@ -1279,10 +1341,22 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepHedgehog(Gear: PGear);
+var tX: hwFloat;
 begin
-if WorldWrap(Gear) and (WorldEdge <> weBounce) and 
-  (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) then
-   CurAmmoGear^.PortalCounter:= 1;
+CheckGearDrowning(Gear);
+if Gear = nil then exit;
+tX:= Gear^.X;
+if WorldWrap(Gear) then
+    begin
+    if (WorldEdge <> weBounce) and (Gear = CurrentHedgehog^.Gear) and 
+       (CurAmmoGear <> nil) and (CurAmmoGear^.Kind =gtRope) and (CurAmmoGear^.Elasticity <> _0) then
+       CurAmmoGear^.PortalCounter:= 1;
+    if (WorldEdge = weWrap) and ((TestCollisionXwithGear(Gear, 1) <> 0) or (TestCollisionXwithGear(Gear, -1) <> 0))  then
+        begin
+        Gear^.X:= tX;
+        Gear^.dX.isNegative:= (hwRound(tX) > LongInt(leftX) + Gear^.Radius * 2)
+        end
+    end;
 
 CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel;
 if (Gear^.Message and gmDestroy) <> 0 then
@@ -1290,7 +1364,7 @@
     DeleteGear(Gear);
     exit
     end;
-if GameTicks mod 100 = 0 then CheckIce(Gear);
+if GameTicks mod 128 = 0 then CheckIce(Gear);
 (*
 if Gear^.Hedgehog^.Effects[heFrozen] > 0 then
     begin