* some changes/cleanups to portal, still much to do :/ * reverted nemo's temporary loop fix * notice: small loops possible again, so take care :P, bigger onces should be interrupted
authorsheepluva
Tue, 04 May 2010 19:40:57 +0000
changeset 3422 41ae3c48faa0
parent 3421 7c72f4d556d1
child 3423 39e3c8f2e52a
* some changes/cleanups to portal, still much to do :/ * reverted nemo's temporary loop fix * notice: small loops possible again, so take care :P, bigger onces should be interrupted
hedgewars/GSHandlers.inc
hedgewars/GearDrawing.inc
hedgewars/HHHandlers.inc
hedgewars/uFloat.pas
hedgewars/uGears.pas
share/hedgewars/Data/Graphics/Portal.png
--- a/hedgewars/GSHandlers.inc	Tue May 04 17:03:38 2010 +0000
+++ b/hedgewars/GSHandlers.inc	Tue May 04 19:40:57 2010 +0000
@@ -3042,40 +3042,99 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 procedure doStepPortal(Gear: PGear);
-var iterator: PGear;
-    s: hwFloat;
+var iterator, conPortal: PGear;
+    s, acptRadius: hwFloat;
+    noTrap, hasdxy: Boolean;
 begin
-    if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then
+    // destroy portal if ground it was attached too is gone
+    if (Land[hwRound(Gear^.Y), hwRound(Gear^.X)] and $FF00) = 0 then deleteGear(Gear);
+
+    // abort if there is no other portal connected to this one
+    if Gear^.IntersectGear = nil then
+        exit;
+
+    conPortal:= Gear^.IntersectGear;
+
+    // check all gears for stuff to port through
+    iterator:= nil;
+    while true do
         begin
-        if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= nil;
-        DeleteGear(Gear);
-        EXIT;
-        end;
+
+        if iterator = nil then
+            iterator:= GearsList // start
+        else
+            iterator:= iterator^.NextGear; // iterate through GearsList
         
-    if Gear^.IntersectGear <> nil then
-    //if (Gear^.IntersectGear <> nil) then
-        begin
-        iterator:= GearsList;
-        while iterator <> nil do
+        if iterator = nil then
+            break; // end of list
+
+        // don't port portals or other gear that wouldn't make sense
+        if (iterator^.Kind = gtPortal)
+        or (iterator^.Kind = gtHealthTag) then
+            continue;
+
+{
+        if (((iterator^.State and gstMoving) = 0) // we don't port non-moving stuff IF the portal entry...
+            and (iterator^.Active = false)
+            and ) then //...
+                continue;
+}
+
+        if (iterator^.Radius > Gear^.Radius) then
+            continue; // sorry, you're too fat!
+
+        // this is the range we accept incoming gears in
+        acptRadius:= Int2hwFloat(iterator^.Radius+Gear^.Radius);
+
+        if (iterator^.X < Gear^.X - acptRadius)
+        or (iterator^.X > Gear^.X + acptRadius)
+        or (iterator^.Y < Gear^.Y - acptRadius)
+        or (iterator^.Y > Gear^.Y + acptRadius) then
+            continue; // too far away!
+
+        hasdxy:= ((iterator^.dX.QWordValue <> 0) or (iterator^.dY.QWordValue <> 0));
+
+        if hasdxy and not (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then
+            continue; // won't port stuff that moves away from me!
+
+        // wow! good candidate there, let's see if the distance really is small enough!
+        if (Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y) > acptRadius) then
+            continue;
+
+        noTrap:= ((not Gear^.dY.isNegative or (Gear^.dY.QWordValue = 0)) // can't be entered from above
+            or ((conPortal^.dY.isNegative or (conPortal^.dY.QWordValue = 0)))); // can't be left downwards;
+ 
+ 
+        // lets see if this one is just stuck in a stuck-loop       
+        if noTrap and (iterator^.dY.QWordValue < _0_1.QWordValue) then
+            continue;
+        
+        iterator^.Active:= true;
+        iterator^.State:= iterator^.State or gstMoving;
+        DeleteCI(iterator);
+
+        s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(conPortal^.dX, conPortal^.dY);
+        iterator^.X:= conPortal^.X + s * conPortal^.dX;
+        iterator^.Y:= conPortal^.Y + s * conPortal^.dY;
+        s:= Distance(iterator^.dX, iterator^.dY) / Distance(conPortal^.dX, conPortal^.dY);
+        iterator^.dX:= s * conPortal^.dX;
+        iterator^.dY:= s * conPortal^.dY;
+        
+        if iterator^.dY.isNegative and (iterator^.dY.QWordValue <> 0) then
+            iterator^.dY:= iterator^.dY + hwAbs(Int2hwFloat(iterator^.Radius) / iterator^.dY) * cGravity;
+
+        // breaks (some) loops
+        if Distance(iterator^.dX, iterator^.dY) > _0_96 then
             begin
-            if (iterator^.Kind <> gtPortal) and (iterator^.PortedCounter < 20) then
-                if (((iterator^.State and gstMoving) <> 0) or (Gear^.IntersectGear^.dY.isNegative and not Gear^.dY.isNegative))
-                    and (hwRound(Distance(Gear^.X-iterator^.X,Gear^.Y-iterator^.Y)) < iterator^.Radius+Gear^.Radius) then // Let's check this one more closely
-                        if (Gear^.dX*iterator^.dX + Gear^.dY*iterator^.dY).isNegative then // make sure object moves towards the portal
-                            begin
-                            inc(iterator^.PortedCounter);
-                            s:= (_1+(Int2hwFloat(Gear^.Radius))) / Distance(Gear^.IntersectGear^.dX, Gear^.IntersectGear^.dY);
-                            iterator^.X:= Gear^.IntersectGear^.X + s * Gear^.IntersectGear^.dX;
-                            iterator^.Y:= Gear^.IntersectGear^.Y + s * Gear^.IntersectGear^.dY;
-                            s:= Distance(iterator^.dX, iterator^.dY) / Distance(Gear^.IntersectGear^.dX, Gear^.IntersectGear^.dY);
-                            iterator^.dX:= s * Gear^.IntersectGear^.dX;
-                            iterator^.dY:= s * Gear^.IntersectGear^.dY;
-                            end;    
-
-            iterator:= iterator^.NextGear;
+            iterator^.dX:= iterator^.dX + signAs(cGravity * getRandom(1000),iterator^.dX);
+            iterator^.dY:= iterator^.dY + signAs(cGravity * getRandom(1000),iterator^.dY);
+            s:= _0_995 / Distance(iterator^.dX, iterator^.dY);
+            iterator^.dX:= s * iterator^.dX;
+            iterator^.dY:= s * iterator^.dX;
             end;
-// do portal stuff
-        end
+
+        iterator:= iterator^.NextGear;
+        end;
 
 (*
 
@@ -3086,7 +3145,6 @@
 
 procedure doStepMovingPortal(Gear: PGear);
 var x, y, tx, ty: LongInt;//, bx, by, tangle: LongInt;
-    iterator: PGear;
     s, dx, dy: hwFloat;
 begin
 Gear^.X:= Gear^.X + Gear^.dX;
@@ -3099,14 +3157,14 @@
     begin
     if not calcSlopeTangent(Gear, x, y, tx, ty, 255) then
         begin
-        DeleteGear(Gear);
+        deleteGear(Gear);
         EXIT;
         end;
 
     // reject shots at too irregular terrain
-    if DistanceI(tx,ty) < _10 then
+    if DistanceI(tx,ty) < _12 then
         begin
-        DeleteGear(Gear);
+        deleteGear(Gear);
         EXIT;
     end;
     
@@ -3151,7 +3209,7 @@
             if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
             else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2
             else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1;
-        DeleteGear(Gear)
+        deleteGear(Gear)
         end
     else
         begin
@@ -3160,27 +3218,7 @@
             else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2;
         inc(Gear^.Tag);
         Gear^.doStep:= @doStepPortal;
-        if Gear^.IntersectGear <> nil then
-            begin
-            Gear^.IntersectGear^.IntersectGear:= Gear;
-            AllInactive:= false;
-            // This jiggles gears, to ensure a portal connection just placed under a gear takes effect.
-            iterator:= GearsList;
-            while iterator <> nil do
-                begin
-                if iterator^.Kind <> gtPortal then
-                    begin
-                    iterator^.Active:= true;
-                    if iterator^.dY.QWordValue = _0.QWordValue then iterator^.dY.isNegative:= false;
-                    iterator^.State:= iterator^.State or gstMoving;
-                    DeleteCI(iterator);
-                    inc(iterator^.dY.QWordValue,10);
-                    end;
-                iterator:= iterator^.NextGear
-                end;
-            doStepPortal(Gear);
-            if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.doStep(Gear^.IntersectGear);
-            end
+        if Gear^.IntersectGear <> nil then Gear^.IntersectGear^.IntersectGear:= Gear;
         end
     end
 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then
@@ -3189,7 +3227,7 @@
         if Gear^.IntersectGear = nil then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
         else if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2
         else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1;
-    DeleteGear(Gear);
+    deleteGear(Gear);
     end;
 end;
 
--- a/hedgewars/GearDrawing.inc	Tue May 04 17:03:38 2010 +0000
+++ b/hedgewars/GearDrawing.inc	Tue May 04 19:40:57 2010 +0000
@@ -602,7 +602,12 @@
                   end;
        gtBall: DrawRotatedf(sprBalls, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag,0, Gear^.DirAngle);
 // Still need portal types and states
-       gtPortal: DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle);
+       gtPortal: begin
+                 if (Gear^.IntersectGear = nil) or (Gear^.IntersectGear^.IntersectGear <> Gear) then // = is portal unlinked?
+                    DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle)
+                 else
+                    DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 4 + Gear^.Tag div 2, hwSign(Gear^.dX), Gear^.DirAngle)
+                 end;
 
        gtDrill: DrawRotated(sprDrill, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
 
--- a/hedgewars/HHHandlers.inc	Tue May 04 17:03:38 2010 +0000
+++ b/hedgewars/HHHandlers.inc	Tue May 04 19:40:57 2010 +0000
@@ -163,7 +163,6 @@
                                  portal:= nil;
                                  while iterator <> nil do
                                      begin
-                                     iterator^.PortedCounter:= 0;
                                      if (iterator^.Kind = gtPortal) then
                                          begin
                                          newGear:= iterator;
@@ -172,13 +171,13 @@
                                              begin
                                              if (portal^.uid < newGear^.uid) then 
                                                  begin
-                                                 DeleteGear(portal);
+                                                 deleteGear(portal);
                                                  portal:= newGear
                                                  end
                                              else
                                                  begin
                                                  if newGear^.NextGear = nil then iterator:= nil;
-                                                 DeleteGear(newGear);
+                                                 deleteGear(newGear);
                                                  end
                                              end
                                          else portal:= newGear
--- a/hedgewars/uFloat.pas	Tue May 04 17:03:38 2010 +0000
+++ b/hedgewars/uFloat.pas	Tue May 04 19:40:57 2010 +0000
@@ -116,6 +116,7 @@
               _5: hwFloat = (isNegative: false; QWordValue:  4294967296 * 5);
               _6: hwFloat = (isNegative: false; QWordValue:  4294967296 * 6);
              _10: hwFloat = (isNegative: false; QWordValue:  4294967296 * 10);
+             _12: hwFloat = (isNegative: false; QWordValue:  4294967296 * 12);
              _16: hwFloat = (isNegative: false; QWordValue:  4294967296 * 16);
              _19: hwFloat = (isNegative: false; QWordValue:  4294967296 * 19);
              _20: hwFloat = (isNegative: false; QWordValue:  4294967296 * 20);
--- a/hedgewars/uGears.pas	Tue May 04 17:03:38 2010 +0000
+++ b/hedgewars/uGears.pas	Tue May 04 19:40:57 2010 +0000
@@ -60,8 +60,7 @@
             uid: Longword;
             ImpactSound: TSound; // first sound, others have to be after it in the sounds def.
             nImpactSounds: Word; // count of ImpactSounds
-            SoundChannel: LongInt;
-            PortedCounter: LongWord // TEMPORARY. To break portal loops pending handling it w/ something a bit saner.
+            SoundChannel: LongInt
         end;
 
 var AllInactive: boolean;
@@ -511,7 +510,11 @@
     Gear^.Tex:= nil
     end;
 
-if Gear^.Kind = gtHedgehog then
+// make sure that portals have their link removed before deletion
+if (Gear^.Kind = gtPortal) and (Gear^.IntersectGear <> nil) then
+    Gear^.IntersectGear^.IntersectGear:= nil
+
+else if Gear^.Kind = gtHedgehog then
     if (CurAmmoGear <> nil) and (CurrentHedgehog^.Gear = Gear) then
         begin
         Gear^.Message:= gm_Destroy;
@@ -859,7 +862,6 @@
     tmpGear:= nil;
     while iterator <> nil do
         begin
-        iterator^.PortedCounter:= 0;
         if (iterator^.Kind = gtPortal) then 
             begin
             tmpGear:= iterator;
Binary file share/hedgewars/Data/Graphics/Portal.png has changed