hedgewars/uGearsUtils.pas
branchwebgl
changeset 9127 e350500c4edb
parent 8833 c13ebed437cb
parent 9080 9b42757d7e71
child 9160 fc46e75f6b72
--- a/hedgewars/uGearsUtils.pas	Thu Apr 04 14:37:19 2013 +0200
+++ b/hedgewars/uGearsUtils.pas	Tue Jun 04 22:28:12 2013 +0200
@@ -1,6 +1,6 @@
 (*
  * Hedgewars, a free turn based strategy game
- * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,13 +31,13 @@
 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
 procedure CheckHHDamage(Gear: PGear);
 procedure CalcRotationDirAngle(Gear: PGear);
-procedure ResurrectHedgehog(gear: PGear);
+procedure ResurrectHedgehog(var gear: PGear);
 
 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt); inline;
 procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
 
 function  CheckGearNear(Gear: PGear; Kind: TGearType; rX, rY: LongInt): PGear;
-function  CheckGearDrowning(Gear: PGear): boolean;
+function  CheckGearDrowning(var Gear: PGear): boolean;
 procedure CheckCollision(Gear: PGear); inline;
 procedure CheckCollisionWithLand(Gear: PGear); inline;
 
@@ -263,6 +263,7 @@
 
 procedure HHHurt(Hedgehog: PHedgehog; Source: TDamageSource);
 begin
+if Hedgehog^.Effects[heFrozen] <> 0 then exit;
 if (Source = dsFall) or (Source = dsExplosion) then
     case random(3) of
         0: PlaySoundV(sndOoff1, Hedgehog^.Team^.voicepack);
@@ -289,32 +290,34 @@
     i: LongWord;
     particle: PVisualGear;
 begin
-    if _0_4 < Gear^.dY then
-        begin
-        dmg := ModifyDamage(1 + hwRound((hwAbs(Gear^.dY) - _0_4) * 70), Gear);
-        PlaySound(sndBump);
-        if dmg < 1 then
-            exit;
+if _0_4 < Gear^.dY then
+    begin
+    dmg := ModifyDamage(1 + hwRound((Gear^.dY - _0_4) * 70), Gear);
+    if Gear^.Hedgehog^.Effects[heFrozen] = 0 then
+         PlaySound(sndBump)
+    else PlaySound(sndFrozenHogImpact);
+    if dmg < 1 then
+        exit;
 
-        for i:= min(12, (3 + dmg div 10)) downto 0 do
-            begin
-            particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
-            if particle <> nil then
-                particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
-            end;
+    for i:= min(12, (3 + dmg div 10)) downto 0 do
+        begin
+        particle := AddVisualGear(hwRound(Gear^.X) - 5 + Random(10), hwRound(Gear^.Y) + 12, vgtDust);
+        if particle <> nil then
+            particle^.dX := particle^.dX + (Gear^.dX.QWordValue / 21474836480);
+        end;
 
-        if (Gear^.Invulnerable) then
-            exit;
+    if (Gear^.Invulnerable) then
+        exit;
 
-        //if _0_6 < Gear^.dY then
-        //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
-        //else
-        //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
+    //if _0_6 < Gear^.dY then
+    //    PlaySound(sndOw4, Gear^.Hedgehog^.Team^.voicepack)
+    //else
+    //    PlaySound(sndOw1, Gear^.Hedgehog^.Team^.voicepack);
 
-        if Gear^.LastDamage <> nil then
-            ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
-        else
-            ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
+    if Gear^.LastDamage <> nil then
+        ApplyDamage(Gear, Gear^.LastDamage, dmg, dsFall)
+    else
+        ApplyDamage(Gear, CurrentHedgehog, dmg, dsFall);
     end
 end;
 
@@ -337,8 +340,8 @@
         Gear^.DirAngle := Gear^.DirAngle - 360
 end;
 
-function CheckGearDrowning(Gear: PGear): boolean;
-var
+function CheckGearDrowning(var Gear: PGear): boolean;
+var 
     skipSpeed, skipAngle, skipDecay: hwFloat;
     i, maxDrops, X, Y: LongInt;
     vdX, vdY: real;
@@ -361,7 +364,7 @@
             else DeleteGear(Gear);
             exit
             end;
-        isSubmersible:= (Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.AmmoType = amJetpack);
+        isSubmersible:= ((Gear = CurrentHedgehog^.Gear) and (CurAmmoGear <> nil) and (CurAmmoGear^.State and gstSubmersible <> 0)) or (Gear^.State and gstSubmersible <> 0);
         skipSpeed := _0_25;
         skipAngle := _1_9;
         skipDecay := _0_87;
@@ -369,7 +372,7 @@
         vdX:= hwFloat2Float(Gear^.dX);
         vdY:= hwFloat2Float(Gear^.dY);
         // this could perhaps be a tiny bit higher.
-        if  (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed)
+        if  (cWaterLine + 64 + Gear^.Radius > Y) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > skipSpeed) 
         and (hwAbs(Gear^.dX) > skipAngle * hwAbs(Gear^.dY)) then
             begin
             Gear^.dY.isNegative := true;
@@ -390,7 +393,11 @@
                     if Gear^.Kind = gtHedgehog then
                         begin
                         if Gear^.Hedgehog^.Effects[heResurrectable] <> 0 then
-                            ResurrectHedgehog(Gear)
+                            begin
+                            // Gear could become nil after this, just exit to skip splashes
+                            ResurrectHedgehog(Gear);
+                            exit
+                            end
                         else
                             begin
                             Gear^.doStep := @doStepDrowningGear;
@@ -401,10 +408,13 @@
                     else
                         Gear^.doStep := @doStepDrowningGear;
                         if Gear^.Kind = gtFlake then
-                            exit // skip splashes
-                end;
+                            exit // skip splashes 
+                end
+            else if (Y > cWaterLine + cVisibleWater*4) and 
+                    ((Gear <> CurrentHedgehog^.Gear) or (CurAmmoGear = nil) or (CurAmmoGear^.State and gstSubmersible = 0)) then
+                Gear^.doStep:= @doStepDrowningGear;
             if ((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
-            or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
+            or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0)
             and (CurAmmoGear^.dY < _0_01))) then
                 if Gear^.Density * Gear^.dY > _1 then
                     PlaySound(sndSplash)
@@ -416,7 +426,7 @@
 
         if ((cReducedQuality and rqPlainSplash) = 0)
         and (((not isSubmersible) and (Y < cWaterLine + 64 + Gear^.Radius))
-        or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and ((CurAmmoGear^.Pos = 0)
+        or (isSubmersible and (Y < cWaterLine + 2 + Gear^.Radius) and (Gear = CurAmmoGear) and ((CurAmmoGear^.Pos = 0)
         and (CurAmmoGear^.dY < _0_01)))) then
             begin
             splash:= AddVisualGear(X, cWaterLine, vgtSplash);
@@ -457,7 +467,7 @@
                         end
                 end
             end;
-        if isSubmersible and (CurAmmoGear^.Pos = 0) then
+        if isSubmersible and (Gear = CurAmmoGear) and (CurAmmoGear^.Pos = 0) then
             CurAmmoGear^.Pos := 1000
         end
     else
@@ -465,7 +475,7 @@
 end;
 
 
-procedure ResurrectHedgehog(gear: PGear);
+procedure ResurrectHedgehog(var gear: PGear);
 var tempTeam : PTeam;
     sparkles: PVisualGear;
     gX, gY: LongInt;
@@ -507,7 +517,7 @@
         RenderHealth(gear^.Hedgehog^);
         ScriptCall('onGearResurrect', gear^.uid);
         gear^.State := gstWait;
-    end;
+        end;
     RecountTeamHealth(tempTeam);
 end;