# HG changeset patch # User sheepluva # Date 1273002057 0 # Node ID 41ae3c48faa0e1a5ec6134588f3ba28df2f2cd37 # Parent 7c72f4d556d117dcb79d897fc07bcee49d0e1b42 * 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 diff -r 7c72f4d556d1 -r 41ae3c48faa0 hedgewars/GSHandlers.inc --- 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; diff -r 7c72f4d556d1 -r 41ae3c48faa0 hedgewars/GearDrawing.inc --- 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)); diff -r 7c72f4d556d1 -r 41ae3c48faa0 hedgewars/HHHandlers.inc --- 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 diff -r 7c72f4d556d1 -r 41ae3c48faa0 hedgewars/uFloat.pas --- 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); diff -r 7c72f4d556d1 -r 41ae3c48faa0 hedgewars/uGears.pas --- 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; diff -r 7c72f4d556d1 -r 41ae3c48faa0 share/hedgewars/Data/Graphics/Portal.png Binary file share/hedgewars/Data/Graphics/Portal.png has changed