11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. |
12 * GNU General Public License for more details. |
13 * |
13 * |
14 * You should have received a copy of the GNU General Public License |
14 * You should have received a copy of the GNU General Public License |
15 * along with this program; if not, write to the Free Software |
15 * along with this program; if not, write to the Free Software |
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 *) |
17 *) |
18 |
18 |
19 {$INCLUDE "options.inc"} |
19 {$INCLUDE "options.inc"} |
20 |
20 |
21 unit uLand; |
21 unit uLand; |
22 interface |
22 interface |
23 uses SDLh, uLandTemplates, uFloat, uConsts, uTypes, uAILandMarks; |
23 uses SDLh, uLandTemplates, uConsts, uTypes, uAILandMarks; |
24 |
24 |
25 procedure initModule; |
25 procedure initModule; |
26 procedure freeModule; |
26 procedure freeModule; |
27 procedure DrawBottomBorder; |
27 procedure DrawBottomBorder; |
28 procedure GenMap; |
28 procedure GenMap; |
29 procedure GenPreview(out Preview: TPreview); |
29 procedure GenPreview(out Preview: TPreview); |
|
30 procedure GenPreviewAlpha(out Preview: TPreviewAlpha); |
30 |
31 |
31 implementation |
32 implementation |
32 uses uConsole, uStore, uRandom, uLandObjects, uIO, uLandTexture, SysUtils, |
33 uses uConsole, uStore, uRandom, uLandObjects, uIO, uLandTexture, SysUtils, |
33 uVariables, uUtils, uCommands, adler32, uDebug, uLandPainted, uTextures, |
34 uVariables, uUtils, uCommands, adler32, uDebug, uLandPainted, uTextures, |
34 uLandGenMaze, uLandOutline, uPhysFSLayer; |
35 uLandGenMaze, uPhysFSLayer, uScript, uLandGenPerlin, |
|
36 uLandGenTemplateBased, uLandUtils; |
35 |
37 |
36 var digest: shortstring; |
38 var digest: shortstring; |
37 |
39 maskOnly: boolean; |
38 procedure ResizeLand(width, height: LongWord); |
40 |
39 var potW, potH: LongInt; |
41 |
40 begin |
42 procedure PrettifyLandAlpha(); |
41 potW:= toPowerOf2(width); |
43 begin |
42 potH:= toPowerOf2(height); |
44 if (cReducedQuality and rqBlurryLand) <> 0 then |
43 if (potW <> LAND_WIDTH) or (potH <> LAND_HEIGHT) then |
45 PrettifyAlpha2D(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2) |
44 begin |
|
45 LAND_WIDTH:= potW; |
|
46 LAND_HEIGHT:= potH; |
|
47 LAND_WIDTH_MASK:= not(LAND_WIDTH-1); |
|
48 LAND_HEIGHT_MASK:= not(LAND_HEIGHT-1); |
|
49 cWaterLine:= LAND_HEIGHT; |
|
50 if (cReducedQuality and rqBlurryLand) = 0 then |
|
51 SetLength(LandPixels, LAND_HEIGHT, LAND_WIDTH) |
|
52 else |
46 else |
53 SetLength(LandPixels, LAND_HEIGHT div 2, LAND_WIDTH div 2); |
47 PrettifyAlpha2D(LandPixels, LAND_HEIGHT, LAND_WIDTH); |
54 |
48 end; |
55 SetLength(Land, LAND_HEIGHT, LAND_WIDTH); |
|
56 SetLength(LandDirty, (LAND_HEIGHT div 32), (LAND_WIDTH div 32)); |
|
57 // 0.5 is already approaching on unplayable |
|
58 if (width div 4096 >= 2) or (height div 2048 >= 2) then cMaxZoomLevel:= 0.5; |
|
59 cMinMaxZoomLevelDelta:= cMaxZoomLevel - cMinZoomLevel |
|
60 end; |
|
61 end; |
|
62 |
|
63 |
49 |
64 procedure DrawBorderFromImage(Surface: PSDL_Surface); |
50 procedure DrawBorderFromImage(Surface: PSDL_Surface); |
65 var tmpsurf: PSDL_Surface; |
51 var tmpsurf: PSDL_Surface; |
66 r, rr: TSDL_Rect; |
52 r, rr: TSDL_Rect; |
67 x, yd, yu: LongInt; |
53 x, yd, yu: LongInt; |
|
54 targetMask: Word; |
68 begin |
55 begin |
69 tmpsurf:= LoadDataImage(ptCurrTheme, 'Border', ifCritical or ifIgnoreCaps or ifTransparent); |
56 tmpsurf:= LoadDataImage(ptCurrTheme, 'Border', ifCritical or ifIgnoreCaps or ifTransparent); |
|
57 |
|
58 // if mask only, all land gets filled with landtex and therefore needs borders |
|
59 if maskOnly then |
|
60 targetMask:= lfLandMask |
|
61 else |
|
62 targetMask:= lfBasic; |
|
63 |
70 for x:= 0 to LAND_WIDTH - 1 do |
64 for x:= 0 to LAND_WIDTH - 1 do |
71 begin |
65 begin |
72 yd:= LAND_HEIGHT - 1; |
66 yd:= LAND_HEIGHT - 1; |
73 repeat |
67 repeat |
74 while (yd > 0) and (Land[yd, x] = 0) do dec(yd); |
68 while (yd > 0) and ((Land[yd, x] and targetMask) = 0) do dec(yd); |
75 |
69 |
76 if (yd < 0) then |
70 if (yd < 0) then |
77 yd:= 0; |
71 yd:= 0; |
78 |
72 |
79 while (yd < LAND_HEIGHT) and (Land[yd, x] <> 0) do |
73 while (yd < LAND_HEIGHT) and ((Land[yd, x] and targetMask) <> 0) do |
80 inc(yd); |
74 inc(yd); |
81 dec(yd); |
75 dec(yd); |
82 yu:= yd; |
76 yu:= yd; |
83 |
77 |
84 while (yu > 0 ) and (Land[yu, x] <> 0) do dec(yu); |
78 while (yu > 0 ) and ((Land[yu, x] and targetMask) <> 0) do dec(yu); |
85 while (yu < yd ) and (Land[yu, x] = 0) do inc(yu); |
79 while (yu < yd ) and ((Land[yu, x] and targetMask) = 0) do inc(yu); |
86 |
80 |
87 if (yd < LAND_HEIGHT - 1) and ((yd - yu) >= 16) then |
81 if (yd < LAND_HEIGHT - 1) and ((yd - yu) >= 16) then |
88 begin |
82 begin |
89 rr.x:= x; |
83 rr.x:= x; |
90 rr.y:= yd - 15; |
84 rr.y:= yd - 15; |
142 begin |
136 begin |
143 if s > y then s:= y; |
137 if s > y then s:= y; |
144 if s + 8 > y then |
138 if s + 8 > y then |
145 begin |
139 begin |
146 if ((x + y) and 16) = 0 then c:= c1 else c:= c2; |
140 if ((x + y) and 16) = 0 then c:= c1 else c:= c2; |
147 |
141 |
148 if (cReducedQuality and rqBlurryLand) = 0 then |
142 if (cReducedQuality and rqBlurryLand) = 0 then |
149 LandPixels[y, x]:= c |
143 LandPixels[y, x]:= c |
150 else |
144 else |
151 LandPixels[y div 2, x div 2]:= c |
145 LandPixels[y div 2, x div 2]:= c |
152 end; |
146 end; |
153 end; |
147 end; |
154 |
148 |
155 // horizontal |
149 // horizontal |
156 s:= LAND_WIDTH; |
150 s:= LAND_WIDTH; |
157 |
151 |
158 for y:= 0 to LAND_HEIGHT - 1 do |
152 for y:= 0 to LAND_HEIGHT - 1 do |
159 for x:= 0 to LAND_WIDTH - 1 do |
153 for x:= 0 to LAND_WIDTH - 1 do |
160 if LandPixels[y, x] = 0 then |
154 if Land[y, x] = 0 then |
161 if s < x then |
155 if s < x then |
162 begin |
156 begin |
163 for i:= max(s, x - 8) to x - 1 do |
157 for i:= max(s, x - 8) to x - 1 do |
164 begin |
158 begin |
165 if ((y + i) and 16) = 0 then c:= c1 else c:= c2; |
159 if ((y + i) and 16) = 0 then c:= c1 else c:= c2; |
166 |
160 |
167 if (cReducedQuality and rqBlurryLand) = 0 then |
161 if (cReducedQuality and rqBlurryLand) = 0 then |
168 LandPixels[y, i]:= c |
162 LandPixels[y, i]:= c |
169 else |
163 else |
170 LandPixels[y div 2, i div 2]:= c |
164 LandPixels[y div 2, i div 2]:= c |
171 end; |
165 end; |
176 begin |
170 begin |
177 if s > x then s:= x; |
171 if s > x then s:= x; |
178 if s + 8 > x then |
172 if s + 8 > x then |
179 begin |
173 begin |
180 if ((x + y) and 16) = 0 then c:= c1 else c:= c2; |
174 if ((x + y) and 16) = 0 then c:= c1 else c:= c2; |
181 |
175 |
182 if (cReducedQuality and rqBlurryLand) = 0 then |
176 if (cReducedQuality and rqBlurryLand) = 0 then |
183 LandPixels[y, x]:= c |
177 LandPixels[y, x]:= c |
184 else |
178 else |
185 LandPixels[y div 2, x div 2]:= c |
179 LandPixels[y div 2, x div 2]:= c |
186 end; |
180 end; |
187 end |
181 end |
188 end; |
182 end; |
189 |
183 |
190 procedure ColorizeLand(Surface: PSDL_Surface); |
184 procedure ColorizeLand(Surface: PSDL_Surface); |
191 var tmpsurf: PSDL_Surface; |
185 var tmpsurf: PSDL_Surface; |
192 r: TSDL_Rect; |
186 r: TSDL_Rect; |
|
187 y: LongInt; // stupid SDL 1.2 uses stupid SmallInt for y which limits us to 32767. But is even worse if LandTex is large, can overflow on 32767 map. |
193 begin |
188 begin |
194 tmpsurf:= LoadDataImage(ptCurrTheme, 'LandTex', ifCritical or ifIgnoreCaps); |
189 tmpsurf:= LoadDataImage(ptCurrTheme, 'LandTex', ifCritical or ifIgnoreCaps); |
195 r.y:= 0; |
190 r.y:= 0; |
196 while r.y < LAND_HEIGHT do |
191 y:= 0; |
197 begin |
192 while y < LAND_HEIGHT do |
|
193 begin |
198 r.x:= 0; |
194 r.x:= 0; |
199 while r.x < LAND_WIDTH do |
195 while r.x < LAND_WIDTH do |
200 begin |
196 begin |
201 SDL_UpperBlit(tmpsurf, nil, Surface, @r); |
197 SDL_UpperBlit(tmpsurf, nil, Surface, @r); |
202 inc(r.x, tmpsurf^.w) |
198 inc(r.x, tmpsurf^.w) |
|
199 end; |
|
200 inc(y, tmpsurf^.h); |
|
201 r.y:= y |
203 end; |
202 end; |
204 inc(r.y, tmpsurf^.h) |
|
205 end; |
|
206 SDL_FreeSurface(tmpsurf); |
203 SDL_FreeSurface(tmpsurf); |
207 |
204 |
208 // freed in freeModule() below |
205 // freed in freeModule() below |
209 LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifTransparent); |
206 LandBackSurface:= LoadDataImage(ptCurrTheme, 'LandBackTex', ifIgnoreCaps or ifTransparent); |
210 if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface); |
207 if (LandBackSurface <> nil) and GrayScale then Surface2GrayScale(LandBackSurface); |
211 end; |
208 end; |
212 |
209 |
213 procedure SetPoints(var Template: TEdgeTemplate; var pa: TPixAr; fps: PPointArray); |
|
214 var i: LongInt; |
|
215 begin |
|
216 with Template do |
|
217 begin |
|
218 pa.Count:= BasePointsCount; |
|
219 for i:= 0 to pred(pa.Count) do |
|
220 begin |
|
221 pa.ar[i].x:= BasePoints^[i].x + LongInt(GetRandom(BasePoints^[i].w)); |
|
222 if pa.ar[i].x <> NTPX then |
|
223 pa.ar[i].x:= pa.ar[i].x + ((LAND_WIDTH - Template.TemplateWidth) div 2); |
|
224 pa.ar[i].y:= BasePoints^[i].y + LongInt(GetRandom(BasePoints^[i].h)) + LAND_HEIGHT - LongInt(Template.TemplateHeight) |
|
225 end; |
|
226 |
|
227 if canMirror then |
|
228 if getrandom(2) = 0 then |
|
229 begin |
|
230 for i:= 0 to pred(BasePointsCount) do |
|
231 if pa.ar[i].x <> NTPX then |
|
232 pa.ar[i].x:= LAND_WIDTH - 1 - pa.ar[i].x; |
|
233 for i:= 0 to pred(FillPointsCount) do |
|
234 fps^[i].x:= LAND_WIDTH - 1 - fps^[i].x; |
|
235 end; |
|
236 |
|
237 (* Experiment in making this option more useful |
|
238 if ((not isNegative) and (cTemplateFilter = 4)) or |
|
239 (canFlip and (getrandom(2) = 0)) then |
|
240 begin |
|
241 for i:= 0 to pred(BasePointsCount) do |
|
242 begin |
|
243 pa.ar[i].y:= LAND_HEIGHT - 1 - pa.ar[i].y + (LAND_HEIGHT - TemplateHeight) * 2; |
|
244 if pa.ar[i].y > LAND_HEIGHT - 1 then |
|
245 pa.ar[i].y:= LAND_HEIGHT - 1; |
|
246 end; |
|
247 for i:= 0 to pred(FillPointsCount) do |
|
248 begin |
|
249 FillPoints^[i].y:= LAND_HEIGHT - 1 - FillPoints^[i].y + (LAND_HEIGHT - TemplateHeight) * 2; |
|
250 if FillPoints^[i].y > LAND_HEIGHT - 1 then |
|
251 FillPoints^[i].y:= LAND_HEIGHT - 1; |
|
252 end; |
|
253 end; |
|
254 end |
|
255 *) |
|
256 // template recycling. Pull these off the floor a bit |
|
257 if (not isNegative) and (cTemplateFilter = 4) then |
|
258 begin |
|
259 for i:= 0 to pred(BasePointsCount) do |
|
260 begin |
|
261 dec(pa.ar[i].y, 100); |
|
262 if pa.ar[i].y < 0 then |
|
263 pa.ar[i].y:= 0; |
|
264 end; |
|
265 for i:= 0 to pred(FillPointsCount) do |
|
266 begin |
|
267 dec(fps^[i].y, 100); |
|
268 if fps^[i].y < 0 then |
|
269 fps^[i].y:= 0; |
|
270 end; |
|
271 end; |
|
272 |
|
273 if (canFlip and (getrandom(2) = 0)) then |
|
274 begin |
|
275 for i:= 0 to pred(BasePointsCount) do |
|
276 pa.ar[i].y:= LAND_HEIGHT - 1 - pa.ar[i].y; |
|
277 for i:= 0 to pred(FillPointsCount) do |
|
278 fps^[i].y:= LAND_HEIGHT - 1 - fps^[i].y; |
|
279 end; |
|
280 end |
|
281 end; |
|
282 |
|
283 |
|
284 procedure GenBlank(var Template: TEdgeTemplate); |
|
285 var pa: TPixAr; |
|
286 i: Longword; |
|
287 y, x: Longword; |
|
288 fps: TPointArray; |
|
289 begin |
|
290 fps:=Template.FillPoints^; |
|
291 ResizeLand(Template.TemplateWidth, Template.TemplateHeight); |
|
292 for y:= 0 to LAND_HEIGHT - 1 do |
|
293 for x:= 0 to LAND_WIDTH - 1 do |
|
294 Land[y, x]:= lfBasic; |
|
295 {$HINTS OFF} |
|
296 SetPoints(Template, pa, @fps); |
|
297 {$HINTS ON} |
|
298 for i:= 1 to Template.BezierizeCount do |
|
299 begin |
|
300 BezierizeEdge(pa, _0_5); |
|
301 RandomizePoints(pa); |
|
302 RandomizePoints(pa) |
|
303 end; |
|
304 for i:= 1 to Template.RandPassesCount do |
|
305 RandomizePoints(pa); |
|
306 BezierizeEdge(pa, _0_1); |
|
307 |
|
308 |
|
309 DrawEdge(pa, 0); |
|
310 |
|
311 with Template do |
|
312 for i:= 0 to pred(FillPointsCount) do |
|
313 with fps[i] do |
|
314 FillLand(x, y); |
|
315 |
|
316 DrawEdge(pa, lfBasic); |
|
317 |
|
318 MaxHedgehogs:= Template.MaxHedgehogs; |
|
319 hasGirders:= Template.hasGirders; |
|
320 playHeight:= Template.TemplateHeight; |
|
321 playWidth:= Template.TemplateWidth; |
|
322 leftX:= ((LAND_WIDTH - playWidth) div 2); |
|
323 rightX:= (playWidth + ((LAND_WIDTH - playWidth) div 2)) - 1; |
|
324 topY:= LAND_HEIGHT - playHeight; |
|
325 |
|
326 // HACK: force to only cavern even if a cavern map is invertable if cTemplateFilter = 4 ? |
|
327 if (cTemplateFilter = 4) |
|
328 or (Template.canInvert and (getrandom(2) = 0)) |
|
329 or (not Template.canInvert and Template.isNegative) then |
|
330 begin |
|
331 hasBorder:= true; |
|
332 for y:= 0 to LAND_HEIGHT - 1 do |
|
333 for x:= 0 to LAND_WIDTH - 1 do |
|
334 if (y < topY) or (x < leftX) or (x > rightX) then |
|
335 Land[y, x]:= 0 |
|
336 else |
|
337 begin |
|
338 if Land[y, x] = 0 then |
|
339 Land[y, x]:= lfBasic |
|
340 else if Land[y, x] = lfBasic then |
|
341 Land[y, x]:= 0; |
|
342 end; |
|
343 end; |
|
344 end; |
|
345 |
210 |
346 procedure GenDrawnMap; |
211 procedure GenDrawnMap; |
347 begin |
212 begin |
348 ResizeLand(4096, 2048); |
213 ResizeLand(4096, 2048); |
349 uLandPainted.Draw; |
214 uLandPainted.Draw; |
431 if gameFlags and gfShoppaBorder = 0 then DrawBorderFromImage(tmpsurf); |
296 if gameFlags and gfShoppaBorder = 0 then DrawBorderFromImage(tmpsurf); |
432 AddOnLandObjects(tmpsurf); |
297 AddOnLandObjects(tmpsurf); |
433 |
298 |
434 LandSurface2LandPixels(tmpsurf); |
299 LandSurface2LandPixels(tmpsurf); |
435 SDL_FreeSurface(tmpsurf); |
300 SDL_FreeSurface(tmpsurf); |
436 |
301 |
437 if gameFlags and gfShoppaBorder <> 0 then DrawShoppaBorder; |
302 if gameFlags and gfShoppaBorder <> 0 then DrawShoppaBorder; |
438 |
303 |
439 for x:= leftX+2 to rightX-2 do |
304 for x:= leftX+2 to rightX-2 do |
440 for y:= topY+2 to LAND_HEIGHT-3 do |
305 for y:= topY+2 to LAND_HEIGHT-3 do |
441 if (Land[y, x] = 0) and |
306 if (Land[y, x] = 0) and |
442 (((Land[y, x-1] = lfBasic) and ((Land[y+1,x] = lfBasic)) or (Land[y-1,x] = lfBasic)) or |
307 (((Land[y, x-1] = lfBasic) and ((Land[y+1,x] = lfBasic)) or (Land[y-1,x] = lfBasic)) or |
443 ((Land[y, x+1] = lfBasic) and ((Land[y-1,x] = lfBasic) or (Land[y+1,x] = lfBasic)))) then |
308 ((Land[y, x+1] = lfBasic) and ((Land[y-1,x] = lfBasic) or (Land[y+1,x] = lfBasic)))) then |
444 begin |
309 begin |
445 if (cReducedQuality and rqBlurryLand) = 0 then |
310 if (cReducedQuality and rqBlurryLand) = 0 then |
446 begin |
311 begin |
447 if (Land[y, x-1] = lfBasic) and (LandPixels[y, x-1] and AMask <> 0) then |
312 if (Land[y, x-1] = lfBasic) and (LandPixels[y, x-1] and AMask <> 0) then |
448 LandPixels[y, x]:= LandPixels[y, x-1] |
313 LandPixels[y, x]:= LandPixels[y, x-1] |
449 |
314 |
450 else if (Land[y, x+1] = lfBasic) and (LandPixels[y, x+1] and AMask <> 0) then |
315 else if (Land[y, x+1] = lfBasic) and (LandPixels[y, x+1] and AMask <> 0) then |
451 LandPixels[y, x]:= LandPixels[y, x+1] |
316 LandPixels[y, x]:= LandPixels[y, x+1] |
452 |
317 |
453 else if (Land[y-1, x] = lfBasic) and (LandPixels[y-1, x] and AMask <> 0) then |
318 else if (Land[y-1, x] = lfBasic) and (LandPixels[y-1, x] and AMask <> 0) then |
454 LandPixels[y, x]:= LandPixels[y-1, x] |
319 LandPixels[y, x]:= LandPixels[y-1, x] |
455 |
320 |
456 else if (Land[y+1, x] = lfBasic) and (LandPixels[y+1, x] and AMask <> 0) then |
321 else if (Land[y+1, x] = lfBasic) and (LandPixels[y+1, x] and AMask <> 0) then |
457 LandPixels[y, x]:= LandPixels[y+1, x]; |
322 LandPixels[y, x]:= LandPixels[y+1, x]; |
458 |
323 |
459 if (((LandPixels[y,x] and AMask) shr AShift) > 10) then |
324 if (((LandPixels[y,x] and AMask) shr AShift) > 10) then |
460 LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (128 shl AShift) |
325 LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (128 shl AShift) |
461 end; |
326 end; |
462 Land[y,x]:= lfObject |
327 Land[y,x]:= lfObject |
463 end |
328 end |
468 ((Land[y, x+1] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y-2,x] = lfBasic)) or |
333 ((Land[y, x+1] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y-2,x] = lfBasic)) or |
469 ((Land[y+1, x] = lfBasic) and (Land[y+1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or |
334 ((Land[y+1, x] = lfBasic) and (Land[y+1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or |
470 ((Land[y-1, x] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or |
335 ((Land[y-1, x] = lfBasic) and (Land[y-1,x+1] = lfBasic) and (Land[y,x+2] = lfBasic)) or |
471 ((Land[y+1, x] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic)) or |
336 ((Land[y+1, x] = lfBasic) and (Land[y+1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic)) or |
472 ((Land[y-1, x] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic))) then |
337 ((Land[y-1, x] = lfBasic) and (Land[y-1,x-1] = lfBasic) and (Land[y,x-2] = lfBasic))) then |
473 |
338 |
474 begin |
339 begin |
475 |
340 |
476 if (cReducedQuality and rqBlurryLand) = 0 then |
341 if (cReducedQuality and rqBlurryLand) = 0 then |
477 |
342 |
478 begin |
343 begin |
479 |
344 |
480 if (Land[y, x-1] = lfBasic) and (LandPixels[y,x-1] and AMask <> 0) then |
345 if (Land[y, x-1] = lfBasic) and (LandPixels[y,x-1] and AMask <> 0) then |
481 LandPixels[y, x]:= LandPixels[y, x-1] |
346 LandPixels[y, x]:= LandPixels[y, x-1] |
482 |
347 |
483 else if (Land[y, x+1] = lfBasic) and (LandPixels[y,x+1] and AMask <> 0) then |
348 else if (Land[y, x+1] = lfBasic) and (LandPixels[y,x+1] and AMask <> 0) then |
484 LandPixels[y, x]:= LandPixels[y, x+1] |
349 LandPixels[y, x]:= LandPixels[y, x+1] |
485 |
350 |
486 else if (Land[y+1, x] = lfBasic) and (LandPixels[y+1,x] and AMask <> 0) then |
351 else if (Land[y+1, x] = lfBasic) and (LandPixels[y+1,x] and AMask <> 0) then |
487 LandPixels[y, x]:= LandPixels[y+1, x] |
352 LandPixels[y, x]:= LandPixels[y+1, x] |
488 |
353 |
489 else if (Land[y-1, x] = lfBasic) and (LandPixels[y-1,x] and AMask <> 0) then |
354 else if (Land[y-1, x] = lfBasic) and (LandPixels[y-1,x] and AMask <> 0) then |
490 LandPixels[y, x]:= LandPixels[y-1, x]; |
355 LandPixels[y, x]:= LandPixels[y-1, x]; |
491 |
356 |
492 if (((LandPixels[y,x] and AMask) shr AShift) > 10) then |
357 if (((LandPixels[y,x] and AMask) shr AShift) > 10) then |
493 LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (64 shl AShift) |
358 LandPixels[y,x]:= (LandPixels[y,x] and (not AMask)) or (64 shl AShift) |
494 end; |
359 end; |
495 Land[y,x]:= lfObject |
360 Land[y,x]:= lfObject |
496 end; |
361 end; |
514 |
379 |
515 tmpsurf:= LoadDataImage(ptForts, ClansArray[0]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); |
380 tmpsurf:= LoadDataImage(ptForts, ClansArray[0]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); |
516 BlitImageAndGenerateCollisionInfo(leftX+150, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); |
381 BlitImageAndGenerateCollisionInfo(leftX+150, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); |
517 SDL_FreeSurface(tmpsurf); |
382 SDL_FreeSurface(tmpsurf); |
518 |
383 |
519 tmpsurf:= LoadDataImage(ptForts, ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); |
384 // not critical because if no R we can fallback to mirrored L |
520 BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); |
385 tmpsurf:= LoadDataImage(ptForts, ClansArray[1]^.Teams[0]^.FortName + 'R', ifAlpha or ifTransparent or ifIgnoreCaps); |
|
386 // fallback |
|
387 if tmpsurf = nil then |
|
388 begin |
|
389 tmpsurf:= LoadDataImage(ptForts, ClansArray[1]^.Teams[0]^.FortName + 'L', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps); |
|
390 BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf, 0, true); |
|
391 end |
|
392 else |
|
393 BlitImageAndGenerateCollisionInfo(rightX - 150 - tmpsurf^.w, LAND_HEIGHT - tmpsurf^.h, tmpsurf^.w, tmpsurf); |
521 SDL_FreeSurface(tmpsurf); |
394 SDL_FreeSurface(tmpsurf); |
522 end; |
395 end; |
523 |
396 |
524 procedure LoadMapConfig; |
397 procedure LoadMapConfig; |
525 var f: PFSFile; |
398 var f: PFSFile; |
719 end; |
592 end; |
720 end; |
593 end; |
721 |
594 |
722 if hasBorder then |
595 if hasBorder then |
723 begin |
596 begin |
724 for y:= 0 to LAND_HEIGHT - 1 do |
597 if WorldEdge = weNone then |
725 for x:= 0 to LAND_WIDTH - 1 do |
598 begin |
726 if (y < topY) or (x < leftX) or (x > rightX) then |
599 for y:= 0 to LAND_HEIGHT - 1 do |
|
600 for x:= 0 to LAND_WIDTH - 1 do |
|
601 if (y < topY) or (x < leftX) or (x > rightX) then |
|
602 Land[y, x]:= lfIndestructible; |
|
603 end |
|
604 else if topY > 0 then |
|
605 begin |
|
606 for y:= 0 to LongInt(topY) - 1 do |
|
607 for x:= 0 to LAND_WIDTH - 1 do |
727 Land[y, x]:= lfIndestructible; |
608 Land[y, x]:= lfIndestructible; |
|
609 end; |
728 // experiment hardcoding cave |
610 // experiment hardcoding cave |
729 // also try basing cave dimensions on map/template dimensions, if they exist |
611 // also try basing cave dimensions on map/template dimensions, if they exist |
730 for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade |
612 for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade |
731 begin |
613 begin |
732 if (WorldEdge <> weBounce) and (WorldEdge <> weWrap) then |
614 if (WorldEdge <> weBounce) and (WorldEdge <> weWrap) then |
800 for x:= leftX div 2 to rightX div 2 do |
682 for x:= leftX div 2 to rightX div 2 do |
801 for y:= topY div 2 to LAND_HEIGHT-1 div 2 do |
683 for y:= topY div 2 to LAND_HEIGHT-1 div 2 do |
802 begin |
684 begin |
803 w:= LandPixels[y div 2,x div 2]; |
685 w:= LandPixels[y div 2,x div 2]; |
804 w:= ((w shr RShift and $FF) + (w shr BShift and $FF) + (w shr GShift and $FF)) div 3; |
686 w:= ((w shr RShift and $FF) + (w shr BShift and $FF) + (w shr GShift and $FF)) div 3; |
805 if w > 255 then |
|
806 w:= 255; |
|
807 w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixels[y div 2,x div 2] and AMask); |
687 w:= (w and $FF shl RShift) or (w and $FF shl BShift) or (w and $FF shl GShift) or (LandPixels[y div 2,x div 2] and AMask); |
808 LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask) |
688 LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask) |
809 end |
689 end |
810 end; |
690 end; |
|
691 |
|
692 PrettifyLandAlpha(); |
|
693 |
|
694 // adjust world edges for borderless maps |
|
695 if (WorldEdge <> weNone) and (not hasBorder) then |
|
696 InitWorldEdges(); |
|
697 |
811 end; |
698 end; |
812 |
699 |
813 procedure GenPreview(out Preview: TPreview); |
700 procedure GenPreview(out Preview: TPreview); |
814 var rh, rw, ox, oy, x, y, xx, yy, t, bit, cbit, lh, lw: LongInt; |
701 var rh, rw, ox, oy, x, y, xx, yy, t, bit, cbit, lh, lw: LongInt; |
815 begin |
702 begin |
816 WriteLnToConsole('Generating preview...'); |
703 WriteLnToConsole('Generating preview...'); |
817 case cMapGen of |
704 case cMapGen of |
818 0: GenBlank(EdgeTemplates[SelectTemplate]); |
705 mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); |
819 1: begin ResizeLand(4096,2048); GenMaze; end; |
706 mgMaze: begin ResizeLand(4096,2048); GenMaze; end; |
820 2: GenDrawnMap; |
707 mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; |
|
708 mgDrawn: GenDrawnMap; |
821 else |
709 else |
822 OutError('Unknown mapgen', true); |
710 OutError('Unknown mapgen', true); |
823 end; |
711 end; |
824 |
712 |
825 // strict scaling needed here since preview assumes a rectangle |
713 // strict scaling needed here since preview assumes a rectangle |
845 begin |
733 begin |
846 t:= 0; |
734 t:= 0; |
847 cbit:= bit * 8; |
735 cbit:= bit * 8; |
848 for yy:= y * lh to y * lh + 7 do |
736 for yy:= y * lh to y * lh + 7 do |
849 for xx:= x * lw + cbit to x * lw + cbit + 7 do |
737 for xx:= x * lw + cbit to x * lw + cbit + 7 do |
850 if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) |
738 if ((yy-oy) and LAND_HEIGHT_MASK = 0) and ((xx-ox) and LAND_WIDTH_MASK = 0) |
851 and (Land[yy-oy, xx-ox] <> 0) then |
739 and (Land[yy-oy, xx-ox] <> 0) then |
852 inc(t); |
740 inc(t); |
853 if t > 8 then |
741 if t > 8 then |
854 Preview[y, x]:= Preview[y, x] or ($80 shr bit); |
742 Preview[y, x]:= Preview[y, x] or ($80 shr bit); |
855 end; |
743 end; |
856 end; |
744 end; |
857 end; |
745 end; |
858 |
746 |
859 |
747 |
|
748 procedure GenPreviewAlpha(out Preview: TPreviewAlpha); |
|
749 var rh, rw, ox, oy, x, y, xx, yy, t, lh, lw: LongInt; |
|
750 begin |
|
751 WriteLnToConsole('Generating preview...'); |
|
752 case cMapGen of |
|
753 mgRandom: GenTemplated(EdgeTemplates[SelectTemplate]); |
|
754 mgMaze: begin ResizeLand(4096,2048); GenMaze; end; |
|
755 mgPerlin: begin ResizeLand(4096,2048); GenPerlin; end; |
|
756 mgDrawn: GenDrawnMap; |
|
757 else |
|
758 OutError('Unknown mapgen', true); |
|
759 end; |
|
760 |
|
761 // strict scaling needed here since preview assumes a rectangle |
|
762 rh:= max(LAND_HEIGHT, 2048); |
|
763 rw:= max(LAND_WIDTH, 4096); |
|
764 ox:= 0; |
|
765 if rw < rh*2 then |
|
766 begin |
|
767 rw:= rh*2; |
|
768 end; |
|
769 if rh < rw div 2 then rh:= rw * 2; |
|
770 |
|
771 ox:= (rw-LAND_WIDTH) div 2; |
|
772 oy:= rh-LAND_HEIGHT; |
|
773 |
|
774 lh:= rh div 128; |
|
775 lw:= rw div 256; |
|
776 for y:= 0 to 127 do |
|
777 for x:= 0 to 255 do |
|
778 begin |
|
779 t:= 0; |
|
780 |
|
781 for yy:= y * lh - oy to y * lh + lh - 1 - oy do |
|
782 for xx:= x * lw - ox to x * lw + lw - 1 - ox do |
|
783 if (yy and LAND_HEIGHT_MASK = 0) and (xx and LAND_WIDTH_MASK = 0) |
|
784 and (Land[yy, xx] <> 0) then |
|
785 inc(t); |
|
786 |
|
787 Preview[y, x]:= t * 255 div (lh * lw); |
|
788 end; |
|
789 end; |
|
790 |
860 procedure chLandCheck(var s: shortstring); |
791 procedure chLandCheck(var s: shortstring); |
861 begin |
792 begin |
862 AddFileLog('CheckLandDigest: ' + s + ' digest : ' + digest); |
793 AddFileLog('CheckLandDigest: ' + s + ' digest : ' + digest); |
863 if digest = '' then |
794 if digest = '' then |
864 digest:= s |
795 digest:= s |