- nemo's patch for custom cave map dimensions
authorunc0rr
Thu, 29 Jan 2009 17:27:43 +0000
changeset 1776 dd5648e250e4
parent 1775 c7dc2f191347
child 1777 88674c291331
- nemo's patch for custom cave map dimensions - Fix for engine crash when not enough place for hedgehogs
hedgewars.kdevelop
hedgewars/GSHandlers.inc
hedgewars/uGears.pas
hedgewars/uLand.pas
hedgewars/uLandObjects.pas
hedgewars/uLandTemplates.pas
hedgewars/uVisualGears.pas
--- a/hedgewars.kdevelop	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars.kdevelop	Thu Jan 29 17:27:43 2009 +0000
@@ -51,7 +51,9 @@
       <filetype>*.hs</filetype>
       <filetype>*.pro</filetype>
     </filetypes>
-    <blacklist/>
+    <blacklist>
+      <path>template.pas</path>
+    </blacklist>
     <general>
       <activedir/>
     </general>
--- a/hedgewars/GSHandlers.inc	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars/GSHandlers.inc	Thu Jan 29 17:27:43 2009 +0000
@@ -1322,7 +1322,7 @@
 	Gear^.X:= int2hwFloat(LAND_WIDTH + 1024);
 	end;
 
-Gear^.Y:= -_300;
+Gear^.Y:= -_300;  // TODO - consider making this proportional to topY to reduce spread on low maps
 Gear^.dX:= int2hwFloat(TargetPoint.X - 5 * Gear^.Tag * 15);
 
 if int2hwFloat(TargetPoint.Y) - Gear^.Y > _0 then
--- a/hedgewars/uGears.pas	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars/uGears.pas	Thu Jan 29 17:27:43 2009 +0000
@@ -416,7 +416,6 @@
 if CurAmmoGear = Gear then CurAmmoGear:= nil;
 if FollowGear = Gear then FollowGear:= nil;
 RemoveGearFromList(Gear);
-
 Dispose(Gear)
 end;
 
@@ -1375,9 +1374,9 @@
 		if ar[i]^.Gear <> nil then
 			begin
 			ar[i]^.Gear^.dX.isNegative:= hwRound(ar[i]^.Gear^.X) > LAND_WIDTH div 2;
-			ar[i]^.Gear^.Pos:= GetRandom(19);
-			ar[i]:= ar[Count - 1]
+			ar[i]^.Gear^.Pos:= GetRandom(19)
 			end;
+		ar[i]:= ar[Count - 1];
 		dec(Count)
 		end
 	end
@@ -1475,6 +1474,9 @@
         while t >= 0 do
           begin
           inc(i);
+          while hasBorder and ((i = amAirAttack) or (i = amMineStrike) or (i = amNapalm)) do
+              inc(i);
+
           dec(t, Ammoz[i].Probability)
           end;
         PlaySound(sndReinforce, false, CurrentTeam^.voicepack);
--- a/hedgewars/uLand.pas	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars/uLand.pas	Thu Jan 29 17:27:43 2009 +0000
@@ -28,6 +28,11 @@
      LandPixels: TLandArray;
      LandTexture: PTexture = nil;
      LandDirty: TDirtyTag;
+     hasBorder: boolean; // I'm putting this here for now.  I'd like it to be toggleable by user (so user can set a border on a non-cave map) - will turn off air attacks
+     hasGirders: boolean;  // I think should be on template by template basis. some caverns might have open water and large spaces.  Some islands don't need? It might be better to tweak the girder code based upon space above.  dunno.
+     playHeight, playWidth, leftX, rightX, topY: Longword;  // idea is that a template can specify height/width.  Or, a map, a height/width by the dimensions of the image.  If the map has pixels near top of image, it triggers border.  Maybe not a good idea, but, for now?  Could also be used to prevent placing a girder outside play area on maps with hasBorder = true
+
+// in your coding style, it appears to be "isXXXX" for a verb, and "FooBar" for everything else - should be PlayHeight ?
 
 procedure GenMap;
 function  GenPreview: TPreview;
@@ -367,7 +372,7 @@
      for i:= 0 to pred(pa.Count) do
          begin
          pa.ar[i].x:= BasePoints^[i].x + LongInt(GetRandom(BasePoints^[i].w));
-         pa.ar[i].y:= BasePoints^[i].y + LongInt(GetRandom(BasePoints^[i].h))
+         pa.ar[i].y:= BasePoints^[i].y + LongInt(GetRandom(BasePoints^[i].h)) + LAND_HEIGHT - Template.TemplateHeight
          end;
 
      if canMirror then
@@ -496,14 +501,30 @@
 
 DrawEdge(pa, COLOR_LAND);
 
+hasGirders:= Template.hasGirders;
+playHeight:= Template.TemplateHeight;
+playWidth:= Template.TemplateWidth;
+//TryDo(playWidth<>0, 'freakin magic man!  Why the HELL does having a TryDo here make the following calculations work?', true);
+leftX:= ((LAND_WIDTH - playWidth) div 2);
+rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1;
+topY:= LAND_HEIGHT - playHeight;
+
 if (Template.canInvert and (getrandom(2) = 0)) or
     (not Template.canInvert and Template.isNegative) then 
+    begin
+    hasBorder:= true;
     for y:= 0 to LAND_HEIGHT - 1 do
         for x:= 0 to LAND_WIDTH - 1 do
-            if Land[y, x] = 0 then
-                Land[y, x]:= COLOR_LAND
-            else if Land[y, x] = COLOR_LAND then
-                Land[y, x]:= 0;
+            if (y < topY) or (x < leftX) or (x > rightX) then
+                Land[y, x]:= 0
+            else
+            begin
+               if Land[y, x] = 0 then
+                   Land[y, x]:= COLOR_LAND
+               else if Land[y, x] = COLOR_LAND then
+                   Land[y, x]:= 0;
+            end;
+    end;
 end;
 
 function SelectTemplate: LongInt;
@@ -553,14 +574,19 @@
 
 AddProgress;
 
-AddObjects;
-
 AddProgress
 end;
 
 procedure MakeFortsMap;
 var tmpsurf: PSDL_Surface;
 begin
+// For now, defining a fort's playable area as 4096x1536 - there are no tall forts.  The extra height is to avoid triggering border with current code, also if user turns on a border, it'll give a bit more maneuvering room.
+playHeight:= 1536;
+playWidth:= 4096;
+leftX:= (LAND_WIDTH - playWidth) div 2;
+rightX:= ((playWidth + (LAND_WIDTH - playWidth) div 2) - 1);
+topY:= LAND_HEIGHT - playHeight;
+
 WriteLnToConsole('Generating forts land...');
 
 tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[0]^.Teams[0]^.FortName + 'L', true, true, true);
@@ -580,6 +606,13 @@
 tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', true, true, true);
 TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true);
 
+playHeight:= tmpsurf^.h;
+playWidth:= tmpsurf^.w;
+TryDo(playWidth<>0, 'freakin magic man!  Why the HELL does having a TryDo here make the following calculations work?', true);
+leftX:= (LAND_WIDTH - playWidth) div 2;
+rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1;
+topY:= LAND_HEIGHT - playHeight;
+
 TryDo(tmpsurf^.format^.BytesPerPixel = 4, 'Map should be 32bit', true);
 
 BlitImageAndGenerateCollisionInfo(
@@ -591,10 +624,11 @@
 end;
 
 procedure GenMap;
-var x, y: LongInt;
-	c: Longword;
-	isCave: boolean;
+var i, j, t: LongInt;
+	x, y, w, c: Longword;
 begin
+hasBorder:= false;
+hasGirders:= true;
 LoadThemeConfig;
 
 if (GameFlags and gfForts) = 0 then
@@ -605,50 +639,64 @@
 
 {$IFDEF DEBUGFILE}LogLandDigest;{$ENDIF}
 
-isCave:= false;
 // check for land near top
-for x:= 0 to LAND_WIDTH-1 do
-	for y:= 0 to 4 do
+for y:= topY to topY + 5 do
+    for x:= leftX to rightX do
 		if Land[y, x] <> 0 then
 			begin
-			isCave:= true;
+			hasBorder:= true;
 			break;
 			end;
 
-if isCave then
+if hasBorder then
 	begin
+    for y:= 0 to LAND_HEIGHT - 1 do
+        for x:= 0 to LAND_WIDTH - 1 do
+            if (y < topY) or (x < leftX) or (x > rightX) then
+                Land[y, x]:= COLOR_INDESTRUCTIBLE;
 	// experiment hardcoding cave
-	for y:= 0 to LAND_HEIGHT-1 do
-		begin
-		Land[y, 0]:= COLOR_INDESTRUCTIBLE;
-		Land[y, 1]:= COLOR_INDESTRUCTIBLE;
-		Land[y, 2]:= COLOR_INDESTRUCTIBLE;
-		Land[y, LAND_WIDTH-3]:= COLOR_INDESTRUCTIBLE;
-		Land[y, LAND_WIDTH-2]:= COLOR_INDESTRUCTIBLE;
-		Land[y, LAND_WIDTH-1]:= COLOR_INDESTRUCTIBLE;
-		if y mod 32 < 16 then c:= $FF000000
-		else c:= $FF00FFFF;
-		LandPixels[y, 0]:= c;
-		LandPixels[y, 1]:= c;
-		LandPixels[y, 2]:= c;
-		LandPixels[y, LAND_WIDTH-3]:= c;
-		LandPixels[y, LAND_WIDTH-2]:= c;
-		LandPixels[y, LAND_WIDTH-1]:= c;
-		end;
+    // also try basing cave dimensions on map/template dimensions, if they exist
+    for w:= 0 to 5 do // width of 3 allowed worms to be knocked through with grenade
+        begin
+        for y:= topY to LAND_HEIGHT - 1 do
+            begin
+            Land[y, leftX + w]:= COLOR_INDESTRUCTIBLE;
+            Land[y, rightX - w]:= COLOR_INDESTRUCTIBLE;
+            if y mod 32 < 16 then c:= $FF000000
+            else c:= $FF00FFFF;
+            LandPixels[y, leftX + w]:= c;
+            LandPixels[y, rightX - w]:= c;
+            end;
 
-	for x:= 0 to LAND_WIDTH-1 do
-		begin
-		Land[0, x]:= COLOR_INDESTRUCTIBLE;
-		Land[1, x]:= COLOR_INDESTRUCTIBLE;
-		Land[2, x]:= COLOR_INDESTRUCTIBLE;
-		if x mod 32 < 16 then c:= $FF000000
-		else c:= $FF00FFFF;
-		LandPixels[0, x]:= c;
-		LandPixels[1, x]:= c;
-		LandPixels[2, x]:= c;
-		end;
+        for x:= leftX to rightX do
+            begin
+            Land[topY + w, x]:= COLOR_INDESTRUCTIBLE;
+            if x mod 32 < 16 then c:= $FF000000
+            else c:= $FF00FFFF;
+            LandPixels[topY + w, x]:= c;
+            end;
+        end;
+     // This is almost certainly not the right place to do this
+     // I just want it to be disabled after a border is added, which could by by map constraints as well as player desire
+     t:= 0;
+     while (t < cMaxTeams) and (TeamsArray[t] <> nil) do
+         begin
+         for i:= 0 to cMaxHHIndex do
+             if TeamsArray[t]^.Hedgehogs[i].Gear <> nil then
+                 begin
+                 for j:= 0 to cMaxSlotAmmoIndex do
+                     begin
+                     TeamsArray[t]^.Hedgehogs[i].Ammo^[Ammoz[amAirAttack].Slot, j].Count:= 0;
+                     TeamsArray[t]^.Hedgehogs[i].Ammo^[Ammoz[amMineStrike].Slot, j].Count:= 0;
+                     TeamsArray[t]^.Hedgehogs[i].Ammo^[Ammoz[amNapalm].Slot, j].Count:= 0;
+                     end;
+                 end;
+         inc(t);
+         end;
 	end;
 
+if ((GameFlags and gfForts) = 0) and (Pathz[ptMapCurrent] = '') then AddObjects;
+
 UpdateLandTexture(0, LAND_HEIGHT);
 end;
 
--- a/hedgewars/uLandObjects.pas	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars/uLandObjects.pas	Thu Jan 29 17:27:43 2009 +0000
@@ -229,7 +229,7 @@
     Result: boolean;
 begin
 with Obj do
-     if CheckLand(inland, x, y, $FFFFFF) then
+     if CheckLand(inland, x, y, COLOR_LAND) then
         begin
         Result:= true;
         i:= 1;
@@ -309,7 +309,7 @@
 	repeat
 		y:= 8;
 		repeat
-			if CheckLand(r, x, y - 8, $FFFFFF)
+			if CheckLand(r, x, y - 8, COLOR_LAND)
 			and not CheckIntersect(x, y, Width, Height) then
 			begin
 			ar[cnt].x:= x;
@@ -471,13 +471,16 @@
 procedure AddObjects();
 begin
 InitRects;
-AddGirder(256);
-AddGirder(512);
-AddGirder(768);
-AddGirder(1024);
-AddGirder(1280);
-AddGirder(1536);
-AddGirder(1792);
+if hasGirders then
+    begin
+    AddGirder(256);
+    AddGirder(512);
+    AddGirder(768);
+    AddGirder(1024);
+    AddGirder(1280);
+    AddGirder(1536);
+    AddGirder(1792);
+    end;
 AddThemeObjects(ThemeObjects, 8);
 AddProgress;
 FreeRects
--- a/hedgewars/uLandTemplates.pas	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars/uLandTemplates.pas	Thu Jan 29 17:27:43 2009 +0000
@@ -21,7 +21,7 @@
 uses SDLh;
 {$INCLUDE options.inc}
 
-const NTPX = Low(TSDL_Rect.x); 
+const NTPX = Low(TSDL_Rect.x);
 
 type PPointArray = ^TPointArray;
      TPointArray = array[0..64] of TSDL_Rect;
@@ -32,8 +32,9 @@
                      FillPointsCount: Longword;
                      BezierizeCount: Longword;
                      RandPassesCount: Longword;
-                     TemplateHeight, TemplateWidth: LongInt;
+                     TemplateHeight, TemplateWidth: Longword;
                      canMirror, canFlip, isNegative, canInvert: boolean;
+                     hasGirders: boolean;
                      end;
 
 //////////////////////////////////////////////////////////////////////////////
@@ -83,6 +84,7 @@
         RandPassesCount: 12;
         TemplateHeight: 1024; TemplateWidth: 4096;
         canMirror: true; canFlip: false; isNegative: true; canInvert: false;
+        hasGirders: false;  // this map, and some other caves, are cramped enough and have plenty of ceiling. Maybe not all caves though
        )
       );
 
--- a/hedgewars/uVisualGears.pas	Thu Jan 29 14:49:47 2009 +0000
+++ b/hedgewars/uVisualGears.pas	Thu Jan 29 17:27:43 2009 +0000
@@ -91,7 +91,7 @@
 
 if hwRound(Gear^.X) < -cScreenWidth - 64 then Gear^.X:= int2hwFloat(cScreenWidth + LAND_WIDTH) else
 if hwRound(Gear^.X) > cScreenWidth + LAND_WIDTH then Gear^.X:= int2hwFloat(-cScreenWidth - 64);
-if hwRound(Gear^.Y) > (LAND_HEIGHT + 75) then Gear^.Y:= Gear^.Y - int2hwFloat(LAND_HEIGHT + 200)
+if hwRound(Gear^.Y) > (LAND_HEIGHT + 75) then Gear^.Y:= Gear^.Y - int2hwFloat(LAND_HEIGHT-1024) // TODO - configure in theme (jellies for example could use limited range)
 end;
 
 procedure doStepCloud(Gear: PVisualGear; Steps: Longword);
@@ -101,7 +101,7 @@
 
 for i:= 0 to Steps - 1 do
 	begin
-	if hwRound(Gear^.Y) > -160 then
+	if hwRound(Gear^.Y) > LAND_HEIGHT-1184 then // TODO - configure in theme
 		Gear^.dY:= Gear^.dY - _1div50000
 	else
 		Gear^.dY:= Gear^.dY + _1div50000;
@@ -298,7 +298,7 @@
 var i: LongInt;
 begin
 for i:= 0 to cCloudsNumber - 1 do
-    AddVisualGear( - cScreenWidth + i * ((cScreenWidth * 2 + 2304) div (cCloudsNumber + 1)), -160, vgtCloud)
+    AddVisualGear( - cScreenWidth + i * ((cScreenWidth * 2 + 2304) div (cCloudsNumber + 1)), LAND_HEIGHT-1184, vgtCloud)
 end;
 
 initialization