* 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
--- 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