More portal changes. Allows for a multishoot utility. Hopefully not breaking anything.
authornemo
Sun, 02 May 2010 02:58:59 +0000
changeset 3396 e5b3e5f2818e
parent 3395 095273ad0e08
child 3397 c47af0694a7d
More portal changes. Allows for a multishoot utility. Hopefully not breaking anything.
hedgewars/CCHandlers.inc
hedgewars/GSHandlers.inc
hedgewars/GearDrawing.inc
hedgewars/HHHandlers.inc
hedgewars/uConsts.pas
hedgewars/uGears.pas
share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png
--- a/hedgewars/CCHandlers.inc	Sat May 01 21:54:08 2010 +0000
+++ b/hedgewars/CCHandlers.inc	Sun May 02 02:58:59 2010 +0000
@@ -633,8 +633,9 @@
             bSelected:= false;
 
             if bShowAmmoMenu then bShowAmmoMenu:= false
-            else if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or (MultiShootAttacks > 0)
-                or ((Gear^.State and gstHHDriven) = 0) then else bShowAmmoMenu:= true
+            else if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or 
+                    ((MultiShootAttacks > 0) and ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) = 0)) or
+                    ((Gear^.State and gstHHDriven) = 0) then else bShowAmmoMenu:= true
             end
 end;
 
--- a/hedgewars/GSHandlers.inc	Sat May 01 21:54:08 2010 +0000
+++ b/hedgewars/GSHandlers.inc	Sun May 02 02:58:59 2010 +0000
@@ -173,6 +173,8 @@
     tdX, tdY: hwFloat;
     collV, collH: LongInt;
 begin
+if Gear^.dX > _0_995 then Gear^.dX:= _0_995;
+if Gear^.dY > _0_995 then Gear^.dY:= _0_995;
 Gear^.State:= Gear^.State and not gstCollision;
 collV:= 0; 
 collH:= 0;
@@ -1828,8 +1830,7 @@
 
 DeleteCI(HHGear);
 
-OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
-ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+AfterAttack;
 
 HHGear^.State:= HHGear^.State and not (gstAttacking or gstAttacked or gstMoving);
 HHGear^.Message:= HHGear^.Message and not gm_Attack;
@@ -1935,8 +1936,7 @@
 else begin
     PlaySound(sndPlaced);
     DeleteGear(Gear);
-    OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
-    ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^)
+    AfterAttack;
     end;
 
 HHGear^.State:= HHGear^.State and not (gstAttacking or gstAttacked);
@@ -2019,8 +2019,7 @@
     HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
     Msg:= Gear^.Message and not gm_Switch;
     DeleteGear(Gear);
-    OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
-    ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+    AfterAttack;
 
     HHGear:= CurrentHedgehog^.Gear;
     ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
@@ -2798,8 +2797,7 @@
 
 HHGear:= PHedgehog(Gear^.Hedgehog)^.Gear;
 FollowGear:= HHGear;
-OnUsedAmmo(PHedgehog(HHGear^.Hedgehog)^);
-ApplyAmmoChanges(PHedgehog(HHGear^.Hedgehog)^);
+AfterAttack;
 with HHGear^ do
     begin
     State:= State and not gstAttacking;
@@ -3042,49 +3040,67 @@
 
 procedure doStepPortal(Gear: PGear);
 begin
+    if Gear^.IntersectGear <> nil then
+        begin
+// do portal stuff
+        end
+
 (*
-A portal will have a few things it does.
-1) At first, it will move through the air until it collides with a surface. Once it does, it will stop.  At this point we might try a check to verify there is enough terrain for it to be spawned against, and delete. Or we could just let it kinda stick out for now.
 
 2) From then on, if doStepPortal is called and a gear of a radius less than or equal to the portal is within X pixels of the portal (we could also check on moving toward the portal I guess, depends how accurate this needs to be) the portal will then locate the first other portal of the opposite type (there should only be one other one), and move that gear's X/Y to that other portal's location, and modify dX/dY to be relative to that other portal's orientation relative to this portal's orientation.  This might require some tweaking with offsets of a few pixels to avoid getting gears stuck in land.
 
-3) At end of turn, all gtPortal will be deleted.
-
-*)
-(*
-Ok. Here's where I plan to go with this.
-1) Restrict portal gun to X shots.
-2) If on first shot, delete all existing gtPortal
-3) On any other shot, delete any existing portals of type X%2, and spawn a new portal of type X%2 oriented at angle 180° from the portal gun.  It might possibly be worth linking portals with a Gear reference, to save time on scanning through the Gear list every time we need a portal.
 *)
 end;
 
 procedure doStepMovingPortal(Gear: PGear);
-var i, x, y: LongInt;
-    oX, oY: hwFloat;
+var x, y: LongInt;//, tx, ty, bx, by, tangle: LongInt;
 begin
-oX:= Gear^.X;
-oY:= Gear^.Y;
 Gear^.X:= Gear^.X + Gear^.dX;
 Gear^.Y:= Gear^.Y + Gear^.dY;
 x:= hwRound(Gear^.X);
 y:= hwRound(Gear^.Y);
+
+if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and ((Land[y, x] and $FF00) <> 0) then
+    begin
 (* 
-Potential issue, portals embedded in land?
-Also, will need checks on how well portal is placed
-Thought is possibly doing it based on midpoint and two ends, so a bit of rough terrain is still permitted, but not curves.
+This is not quite doing what I want, but basically hoping to avoid portals just sitting out in midair
+Works ok for right angles, aaaand that's about it.
+The opposite approach could be taken, we could determine the angle of the land using sheepluva's code and snap the Angle/DirAngle to it.
+tangle:= Gear^.Angle+1024;
+if tangle > 2048 then dec(tangle,2048);
+tx:= hwRound(Gear^.X+SignAs(AngleSin(tangle), Gear^.dX)*_6);
+ty:= hwRound(Gear^.Y-AngleCos(tangle)*_6);
+bx:= hwRound(Gear^.X-SignAs(AngleSin(tangle), Gear^.dX)*_6);
+by:= hwRound(Gear^.Y+AngleCos(tangle)*_6);
 *)
-if ((y and LAND_HEIGHT_MASK) = 0) and ((x and LAND_WIDTH_MASK) = 0) and (Land[y, x] <> 0) then
-    begin
-    inc(Gear^.Tag);
-    Gear^.doStep:= @doStepPortal;
-//    AfterAttack;
+    if ((Gear^.IntersectGear <> nil) and (hwRound(Distance(Gear^.X - Gear^.IntersectGear^.X,Gear^.Y-Gear^.IntersectGear^.Y)) < Gear^.Radius*2)) 
+(*or
+(((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and ((Land[ty, tx] and $FF00) = 0)) or
+(((by and LAND_HEIGHT_MASK) = 0) and ((bx and LAND_WIDTH_MASK) = 0) and ((Land[by, bx] and $FF00) = 0))*)
+    then
+        begin
+        if CurrentHedgehog <> nil then
+            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)
+        end
+    else
+        begin
+        if CurrentHedgehog <> nil then
+            if Gear^.Tag = 2 then CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 1
+            else CurrentHedgehog^.Ammo^[CurrentHedgehog^.CurSlot, CurrentHedgehog^.CurAmmo].Timer:= 2;
+        inc(Gear^.Tag);
+        Gear^.doStep:= @doStepPortal
+        end
     end
-// How laser checks for infinite
 else if (y > cWaterLine + cVisibleWater + Gear^.Radius) or (y < -LAND_WIDTH) or (x > LAND_WIDTH + LAND_WIDTH) or (x < -LAND_WIDTH) then
     begin
+    if CurrentHedgehog <> nil then
+        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);
-//    AfterAttack
     end;
 end;
 
--- a/hedgewars/GearDrawing.inc	Sat May 01 21:54:08 2010 +0000
+++ b/hedgewars/GearDrawing.inc	Sun May 02 02:58:59 2010 +0000
@@ -347,7 +347,10 @@
             amShotgun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle);
             amDEagle: DrawRotated(sprHandDEagle, hx, hy, hwSign(Gear^.dX), aangle);
             amSineGun: DrawRotated(sprHandShotgun, hx, hy, hwSign(Gear^.dX), aangle);
-            amPortalGun: DrawRotatedF(sprPortalGun, hx, hy, 0, hwSign(Gear^.dX), aangle);
+            amPortalGun: if HH^.MultiShootAttacks = 0 then // Add a new Hedgehog value instead of abusing timer?
+                            DrawRotatedF(sprPortalGun, hx, hy, 0, hwSign(Gear^.dX), aangle)
+                      else
+                            DrawRotatedF(sprPortalGun, hx, hy, HH^.Ammo^[HH^.CurSlot, HH^.CurAmmo].Timer, hwSign(Gear^.dX), aangle);
             amSniperRifle: DrawRotatedF(sprSniperRifle, hx, hy, 0, hwSign(Gear^.dX), aangle);
             amBlowTorch: DrawRotated(sprHandBlowTorch, hx, hy, hwSign(Gear^.dX), aangle);
             amCake: DrawRotated(sprHandCake, hx, hy, hwSign(Gear^.dX), aangle);
@@ -599,7 +602,7 @@
                   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, 0,0, Gear^.DirAngle);
+       gtPortal: DrawRotatedf(sprPortal, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, Gear^.Tag, hwSign(Gear^.dX), Gear^.DirAngle);
 
        gtDrill: DrawRotated(sprDrill, hwRound(Gear^.X) + WorldDx, hwRound(Gear^.Y) + WorldDy, 0, DxDy2Angle(Gear^.dY, Gear^.dX));
 
--- a/hedgewars/HHHandlers.inc	Sat May 01 21:54:08 2010 +0000
+++ b/hedgewars/HHHandlers.inc	Sun May 02 02:58:59 2010 +0000
@@ -26,10 +26,11 @@
     begin
     Gear^.Message:= Gear^.Message and not gm_Slot;
 
-    if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0)
-        or (MultiShootAttacks > 0)
-        or ((Gear^.State and gstHHDriven) = 0) then exit;
+    if ((Gear^.State and (gstAttacking or gstAttacked)) <> 0) or
+       ((MultiShootAttacks > 0) and ((Ammo^[CurSlot, CurAmmo].Propz and ammoprop_NoRoundEndHint) = 0)) or
+       ((Gear^.State and gstHHDriven) = 0) then exit;
 
+    MultiShootAttacks:= 0;
     Gear^.Message:= Gear^.Message and not (gm_LJump or gm_HJump);
 
     if CurSlot = slot then
@@ -101,6 +102,7 @@
 procedure Attack(Gear: PGear);
 var xx, yy: hwFloat;
     tmpGear: PVisualGear;
+    newGear, iterator, portal: PGear;
 begin
 bShowFinger:= false;
 with Gear^,
@@ -148,34 +150,53 @@
                           amBee: FollowGear:= AddGear(hwRound(X), hwRound(Y), gtBee,          0, xx*Power/cPowerDivisor, yy*Power/cPowerDivisor, 0);
                       amShotgun: begin
                                  PlaySound(sndShotgunReload);
-                                 CurAmmoGear:= AddGear(hwRound(X), hwRound(Y), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
+                                 AddGear(hwRound(X), hwRound(Y), gtShotgunShot,  0, xx * _0_5, yy * _0_5, 0);
                                  end;
                    amPickHammer: CurAmmoGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y) + cHHRadius, gtPickHammer, 0, _0, _0, 0);
                          amSkip: ParseCommand('/skip', true);
                          amRope: CurAmmoGear:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtRope, 0, xx, yy, 0);
                          amMine: AddGear(hwRound(X) + hwSign(dX) * 7, hwRound(Y), gtMine, gstWait, SignAs(_0_02, dX), _0, 3000);
-                       amDEagle: CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
+                       amDEagle: AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtDEagleShot, 0, xx * _0_5, yy * _0_5, 0);
                       amSineGun: CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtSineGunShot, 0, xx * _0_5, yy * _0_5, 0);
-(*
-Ok. Here's where I plan to go with this.
-1) Restrict portal gun to X shots.
-2) If on first shot, delete all existing gtPortal
-3) On any other shot, delete any existing portals of type X%2, and spawn a new portal of type X%2 oriented at angle 180° from the portal gun.  It might possibly be worth linking portals with a Gear reference, to save time on scanning through the Gear list every time we need a portal.
-*)
                     amPortalGun: begin
-        //if (Ammo^[CurSlot, CurAmmo].NumPerTurn >= MultiShootAttacks) then
-                                
-
-//CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 0);
-AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 0);
-
+                                 iterator:= GearsList;
+                                 portal:= nil;
+                                 while iterator <> nil do
+                                     begin
+                                     if (iterator^.Kind = gtPortal) then
+                                         begin
+                                         newGear:= iterator;
+                                         iterator:= iterator^.NextGear;
+                                         if (portal <> nil) then
+                                             begin
+                                             if (portal^.uid < newGear^.uid) then 
+                                                 begin
+                                                 DeleteGear(portal);
+                                                 portal:= newGear
+                                                 end
+                                             else
+                                                 begin
+                                                 if newGear^.NextGear = nil then iterator:= nil;
+                                                 DeleteGear(newGear);
+                                                 end
+                                             end
+                                         else portal:= newGear
+                                         end
+                                     else iterator:= iterator^.NextGear
+                                     end;
 
-
+                                 newGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtPortal, 0, xx * _0_6, yy * _0_6, 0);
+                                 if portal <> nil then 
+                                     begin
+                                     newGear^.IntersectGear:= portal;
+                                     if portal^.Tag < 2 then newGear^.Tag:= 2
+                                     end;
+                                 newGear^.Angle:= Angle;
+                                 newGear^.DirAngle:= Angle * 180 / cMaxAngle - 90;
+                                 if Gear^.DirAngle < 0 then Gear^.DirAngle:= Gear^.DirAngle + 360
+                                 else if 360 < Gear^.DirAngle then Gear^.DirAngle:= Gear^.DirAngle - 360;
+                                 Ammo^[CurSlot, CurAmmo].Timer:= 0
                                  end;
-
-
-
-
                   amSniperRifle: begin
                                  PlaySound(sndSniperReload);
                                  CurAmmoGear:= AddGear(hwRound(X + xx * cHHRadius), hwRound(Y + yy * cHHRadius), gtSniperRifleShot, 0, xx * _0_5, yy * _0_5, 0);
@@ -289,8 +310,11 @@
             end
         else
             begin
-            TurnTimeLeft:= Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
-            State:= State or gstAttacked;
+            if ((Ammo^[CurSlot, CurAmmo].Propz) and ammoprop_NoRoundEndHint) = 0 then
+                begin
+                TurnTimeLeft:= Ammoz[Ammo^[CurSlot, CurAmmo].AmmoType].TimeAfterTurn;
+                State:= State or gstAttacked
+                end;
             OnUsedAmmo(CurrentHedgehog^);
             end;
         end
@@ -565,6 +589,8 @@
 procedure doStepHedgehogMoving(Gear: PGear);
 var isFalling: boolean;
 begin
+if Gear^.dX > _0_995 then Gear^.dX:= _0_995;
+if Gear^.dY > _0_995 then Gear^.dY:= _0_995;
 if PHedgehog(Gear^.Hedgehog)^.Unplaced then
    begin
    Gear^.dY:= _0;
--- a/hedgewars/uConsts.pas	Sat May 01 21:54:08 2010 +0000
+++ b/hedgewars/uConsts.pas	Sun May 02 02:58:59 2010 +0000
@@ -1904,6 +1904,7 @@
             Probability: 20;
             NumberInCase: 1;
             Ammo: (Propz: ammoprop_NoRoundEndHint or
+                          ammoprop_AttackInMove or
                           ammoprop_DontHold or
                           ammoprop_Utility;
                 Count: 1;
--- a/hedgewars/uGears.pas	Sat May 01 21:54:08 2010 +0000
+++ b/hedgewars/uGears.pas	Sun May 02 02:58:59 2010 +0000
@@ -81,7 +81,7 @@
 procedure freeModule;
 function  AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
 procedure ProcessGears;
-procedure ResetUtilities;
+procedure EndTurnCleanup;
 procedure ApplyDamage(Gear: PGear; Damage: Longword);
 procedure SetAllToActive;
 procedure SetAllHHToActive;
@@ -736,7 +736,7 @@
                 AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
                 playSound(sndSuddenDeath)
                 end
-            else if (TotalRounds < cSuddenDTurns - 1) then
+            else if (TotalRounds < cSuddenDTurns - 1) and not isInMultiShoot then
                 begin
                 i:= cSuddenDTurns - TotalRounds - 1;
                 s:= inttostr(i);
@@ -771,7 +771,7 @@
                         and ((Gear^.State and gstAttacked) = 0)
                         and (MultiShootAttacks > 0) then OnUsedAmmo(CurrentHedgehog^);
                 
-                ResetUtilities;
+                EndTurnCleanup;
 
                 FreeActionsList; // could send -left, -right and similar commands, so should be called before /nextturn
 
@@ -816,10 +816,11 @@
 inc(GameTicks)
 end;
 
-//Purpose, to reset all transient attributes toggled by a utility.
+//Purpose, to reset all transient attributes toggled by a utility and clean up various gears and effects at end of turn
 //If any of these are set as permanent toggles in the frontend, that needs to be checked and skipped here.
-procedure ResetUtilities;
+procedure EndTurnCleanup;
 var  i: LongInt;
+    tmpGear, iterator: PGear;
 begin
     SpeechText:= ''; // in case it has not been consumed
 
@@ -853,6 +854,18 @@
                      if (GameFlags and gfInvulnerable) = 0 then
                         Gear^.Invulnerable:= false;
                   end;
+    iterator:= GearsList;
+    tmpGear:= nil;
+    while iterator <> nil do
+        begin
+        if (iterator^.Kind = gtPortal) then 
+            begin
+            tmpGear:= iterator;
+            if iterator^.NextGear <> nil then iterator:= iterator^.NextGear;
+            DeleteGear(tmpGear)
+            end
+        else iterator:= iterator^.NextGear;
+        end;
 end;
 
 procedure ApplyDamage(Gear: PGear; Damage: Longword);
Binary file share/hedgewars/Data/Graphics/Hedgehog/amPortalGun.png has changed