1 /***************************************************************************
2 fog.cpp - Fog of war
3 -------------------
4 begin : Sat May 3 2003
5 copyright : (C) 2003 by Gabor Torok
6 email : cctorok@yahoo.com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "../common/constants.h"
19 #include "fog.h"
20 #include "glshape.h"
21 #include "frustum.h"
22 #include "map.h"
23 #include "location.h"
24 #include "mapadapter.h"
25 #include "renderedcreature.h"
26
27 // FIXME: remove this later
28 #include "../scourge.h"
29
30 using namespace std;
31
32 //#define DEBUG_FOG 1
33
34 // how many map spaces in a fog chunk
35 #define FOG_CHUNK_SIZE 4
36
37 #define FOG_WIDTH ( MAP_WIDTH / FOG_CHUNK_SIZE )
38 #define FOG_DEPTH ( MAP_DEPTH / FOG_CHUNK_SIZE )
39
40 // color of transparent fog
41 //#define ER 118
42 //#define EG 110
43 //#define EB 130
44
45 #define ER 192
46 #define EG 192
47 #define EB 210
48 #define EA 128
49
50 //#define DARK_R 0.05f
51 //#define DARK_G 0.04f
52 //#define DARK_B 0.055f
53
54 #define DARK_R 0.0f
55 #define DARK_G 0.0f
56 #define DARK_B 0.0f
57
58 // inverse color of dark shade
59 #define SR static_cast<int>( 255.0f * DARK_R )
60 #define SG static_cast<int>( 255.0f * DARK_G )
61 #define SB static_cast<int>( 255.0f * DARK_B )
62
63 //#define LAMP_RADIUS_SQUARED 36.0f
64 //#define LAMP_RADIUS_SQUARED 64.0f
65
Fog(Map * map,float lampRadiusSquared)66 Fog::Fog( Map *map, float lampRadiusSquared ) {
67 this->lampRadiusSquared = lampRadiusSquared;
68 players = new std::set<RenderedCreature *> [MAP_WIDTH * MAP_DEPTH];
69 this->map = map;
70 createOverlayTexture();
71 createShadeTexture();
72 reset();
73 }
74
~Fog()75 Fog::~Fog() {
76 glDeleteTextures( 1, &overlay_tex );
77 glDeleteTextures( 1, &shade_tex );
78 delete [] players;
79 }
80
reset()81 void Fog::reset() {
82 for ( int x = 0; x < FOG_WIDTH; x++ ) {
83 for ( int y = 0; y < FOG_DEPTH; y++ ) {
84 fog[x][y] = FOG_UNVISITED;
85 players[x + ( y * MAP_WIDTH )].clear();
86 }
87 }
88 }
89
getValue(int mapx,int mapy)90 int Fog::getValue( int mapx, int mapy ) {
91 return fog[mapx / FOG_CHUNK_SIZE][mapy / FOG_CHUNK_SIZE];
92 }
93
visit(RenderedCreature * player)94 void Fog::visit( RenderedCreature *player ) {
95 for ( int x = 0; x < FOG_WIDTH; x++ ) {
96 for ( int y = 0; y < FOG_DEPTH; y++ ) {
97
98 int fx = toint( player->getX() / FOG_CHUNK_SIZE );
99 int fy = toint( player->getY() / FOG_CHUNK_SIZE );
100
101 double d = static_cast<double>( ( fx - x ) * ( fx - x ) ) + static_cast<double>( ( fy - y ) * ( fy - y ) );
102 if ( d <= lampRadiusSquared ) {
103 fog[x][y] = FOG_CLEAR;
104 players[x + ( y * MAP_WIDTH )].insert( player );
105 } else if ( fog[x][y] == FOG_CLEAR ) {
106 players[x + ( y * MAP_WIDTH )].erase( player );
107 if ( players[x + ( y * MAP_WIDTH )].empty() ) {
108 fog[x][y] = FOG_VISITED;
109 }
110 }
111 }
112 }
113 }
114
hideDeadParty()115 void Fog::hideDeadParty() {
116 for ( int i = 0; i < map->getAdapter()->getPartySize(); i++ ) {
117 if ( map->getAdapter()->getParty( i )->getStateMod( StateMod::dead ) ) {
118 for ( int x = 0; x < FOG_WIDTH; x++ ) {
119 for ( int y = 0; y < FOG_DEPTH; y++ ) {
120 if ( fog[x][y] == FOG_CLEAR ) {
121 players[x + ( y * MAP_WIDTH )].erase( map->getAdapter()->getParty( i ) );
122 if ( players[x + ( y * MAP_WIDTH )].empty() ) {
123 fog[x][y] = FOG_VISITED;
124 }
125 }
126 }
127 }
128 }
129 }
130 }
131
getVisibility(int xp,int yp,Shape * shape)132 int Fog::getVisibility( int xp, int yp, Shape *shape ) {
133 int v = FOG_UNVISITED;
134 for ( int x = 0; x < shape->getWidth(); x++ ) {
135 for ( int y = 0; y < shape->getDepth(); y++ ) {
136 int vv = getValue( xp + x, yp - y );
137 if ( vv == FOG_CLEAR ) return FOG_CLEAR;
138 else if ( vv == FOG_VISITED ) v = vv;
139 }
140 }
141 return v;
142 }
143
draw(int sx,int sy,int w,int h,CFrustum * frustum)144 void Fog::draw( int sx, int sy, int w, int h, CFrustum *frustum ) {
145 int fx = sx / FOG_CHUNK_SIZE;
146 int fy = sy / FOG_CHUNK_SIZE;
147 int fw = w / FOG_CHUNK_SIZE;
148 int fh = h / FOG_CHUNK_SIZE;
149 float nn = FOG_CHUNK_SIZE * MUL;
150 int ox = sx % FOG_CHUNK_SIZE;
151 int oy = sy % FOG_CHUNK_SIZE;
152
153 GLfloat minLightX, minLightY, maxLightX, maxLightY;
154 minLightX = minLightY = 2000;
155 maxLightX = maxLightY = 0;
156 bool e[1000];
157 int f[1000];
158 GLfloat p[1000][4];
159 int pCount = 0;
160 for ( int x = 0; x < fw; x ++ ) {
161 for ( int y = 0; y < fh; y ++ ) {
162 int v = fog[ fx + x ][ fy + y ];
163 if ( v == FOG_VISITED ) continue;
164
165 float xp = static_cast<float>( x * FOG_CHUNK_SIZE - ox ) * MUL;
166 float yp = static_cast<float>( y * FOG_CHUNK_SIZE - oy ) * MUL;
167 int z = getHighestZ( ( fx + x ) * FOG_CHUNK_SIZE, ( fy + y ) * FOG_CHUNK_SIZE, FOG_CHUNK_SIZE, FOG_CHUNK_SIZE );
168 float zp = static_cast<float>( z ) * MUL;
169
170 // FIXME: we should check 2d inclusion in screen rect instead
171 if ( !frustum->CubeInFrustum( xp, yp, 0.0f, nn ) )
172 continue;
173
174 // get all screen points of the bounding box; draw bounding rectangle on screen
175 float obj[20][3] = {
176 { xp, yp, zp },
177 { xp, yp + nn, zp },
178 { xp + nn, yp + nn, zp },
179 { xp + nn, yp, zp },
180
181 { xp, yp, zp },
182 { xp, yp, 0 },
183 { xp + nn, yp, 0 },
184 { xp + nn, yp, zp },
185
186 { xp, yp + nn, zp },
187 { xp, yp + nn, 0 },
188 { xp + nn, yp + nn, 0 },
189 { xp + nn, yp + nn, zp },
190
191 { xp, yp, zp },
192 { xp, yp, 0 },
193 { xp, yp + nn, 0 },
194 { xp, yp + nn, zp },
195
196 { xp + nn, yp, zp },
197 { xp + nn, yp, 0 },
198 { xp + nn, yp + nn, 0 },
199 { xp + nn, yp + nn, zp }
200 };
201 GLfloat maxScX, maxScY;
202 GLfloat minScX, minScY;
203
204 maxScX = maxScY = 0;
205 minScX = minScY = 2000;
206 for ( int i = 0; i < 20; i++ ) {
207 GLdouble scx, scy;
208 getScreenXY( ( GLdouble )obj[i][0], ( GLdouble )obj[i][1], ( GLdouble )obj[i][2], &scx, &scy );
209
210 // only show light area for current player
211 if ( v == FOG_CLEAR &&
212 players[x + fx + ( ( y + fy ) * MAP_WIDTH )].find( map->getAdapter()->getPlayer() ) != players[x + fx + ( ( y + fy ) * MAP_WIDTH )].end() ) {
213 if ( scx < minLightX ) minLightX = ( GLfloat )scx;
214 if ( scx > maxLightX ) maxLightX = ( GLfloat )scx;
215 if ( scy < minLightY ) minLightY = ( GLfloat )scy;
216 if ( scy > maxLightY ) maxLightY = ( GLfloat )scy;
217 } else {
218 if ( scx < minScX ) minScX = ( GLfloat )scx;
219 if ( scx > maxScX ) maxScX = ( GLfloat )scx;
220 if ( scy < minScY ) minScY = ( GLfloat )scy;
221 if ( scy > maxScY ) maxScY = ( GLfloat )scy;
222 }
223 }
224
225 if ( v == FOG_CLEAR )
226 continue;
227
228 f[pCount] = v;
229 p[pCount][0] = minScX;
230 p[pCount][1] = minScY;
231 p[pCount][2] = maxScX - minScX;
232 p[pCount][3] = maxScY - minScY;
233
234 e[pCount] = false;
235 if ( ( fy + y > 0 && v != fog[ fx + x ][ fy + y - 1 ] )
236 || ( fx + x > 0 && v != fog[ fx + x - 1 ][ fy + y ] )
237 || ( fx + x < FOG_WIDTH - 1 && v != fog[ fx + x + 1 ][ fy + y ] )
238 || ( fy + y < FOG_DEPTH - 1 && v != fog[ fx + x ][ fy + y + 1 ] ) ) {
239 e[pCount] = true;
240 }
241
242 pCount++;
243 if ( pCount >= 1000 ) break;
244 }
245 }
246
247
248
249 // ***************************
250 // DRAW IT!
251
252 glDisable( GL_TEXTURE_2D );
253 glDisable( GL_CULL_FACE );
254 glDisable( GL_DEPTH_TEST );
255
256 //glBindTexture( GL_TEXTURE_2D, texture );
257
258 glEnable( GL_BLEND );
259 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
260 glColor4f( ER / 255.0f, EG / 255.0f, EB / 255.0f, EA / 255.0f );
261 //glBlendFunc(GL_DST_COLOR, GL_ZERO);
262 //glColor4f( ER / 255.0f, EG / 255.0f, EB / 255.0f, 0.5f);
263
264
265 glPushMatrix();
266 glLoadIdentity();
267
268 // draw a gray rect.
269 if ( map->getAdapter()->
270 intersects( 0, 0,
271 map->getAdapter()->getScreenWidth(),
272 map->getAdapter()->getScreenHeight(),
273 static_cast<int>( minLightX ), static_cast<int>( minLightY ),
274 static_cast<int>( maxLightX - minLightX ),
275 static_cast<int>( maxLightY - minLightY ) ) ) {
276
277
278 glBegin( GL_QUADS );
279
280 glVertex2f( 0, 0 );
281 glVertex2f( 0, minLightY );
282 glVertex2f( map->getAdapter()->getScreenWidth(), minLightY );
283 glVertex2f( map->getAdapter()->getScreenWidth(), 0 );
284
285 glVertex2f( 0, maxLightY );
286 glVertex2f( 0, map->getAdapter()->getScreenHeight() );
287 glVertex2f( map->getAdapter()->getScreenWidth(), map->getAdapter()->getScreenHeight() );
288 glVertex2f( map->getAdapter()->getScreenWidth(), maxLightY );
289
290 glVertex2f( 0, minLightY );
291 glVertex2f( 0, maxLightY );
292 glVertex2f( minLightX, maxLightY );
293 glVertex2f( minLightX, minLightY );
294
295 glVertex2f( maxLightX, minLightY );
296 glVertex2f( maxLightX, maxLightY );
297 glVertex2f( map->getAdapter()->getScreenWidth(), maxLightY );
298 glVertex2f( map->getAdapter()->getScreenWidth(), minLightY );
299
300 glEnd();
301
302
303 // draw the light circle
304 glEnable( GL_TEXTURE_2D );
305 glLoadIdentity();
306 glColor4f( 1, 1, 1, 1 );
307
308 glBindTexture( GL_TEXTURE_2D, overlay_tex );
309 glBegin( GL_TRIANGLE_STRIP );
310
311 glTexCoord2f( 0.0f, 0.0f );
312 glVertex2f( minLightX, minLightY );
313 glTexCoord2f( 1.0f, 0.0f );
314 glVertex2f( maxLightX, minLightY );
315 glTexCoord2f( 0.0f, 1.0f );
316 glVertex2f( minLightX, maxLightY );
317 glTexCoord2f( 1.0f, 1.0f );
318 glVertex2f( maxLightX, maxLightY );
319 glEnd();
320 glDisable( GL_TEXTURE_2D );
321 } else {
322 glBegin( GL_TRIANGLE_STRIP );
323 glVertex2f( 0, 0 );
324 glVertex2f( map->getAdapter()->getScreenWidth(), 0 );
325 glVertex2f( 0, map->getAdapter()->getScreenHeight() );
326 glVertex2f( map->getAdapter()->getScreenWidth(),
327 map->getAdapter()->getScreenHeight() );
328 glEnd();
329 }
330
331 // draw the dark (unvisited) fog
332 glLoadIdentity();
333 glDisable( GL_BLEND );
334 //glColor4f( 0.08f, 0.03f, 0.07f, 0.5f);
335 glColor3f( DARK_R, DARK_G, DARK_B );
336 for ( int i = 0; i < pCount; i++ ) {
337 GLfloat x = p[i][0];
338 GLfloat y = p[i][1];
339 GLfloat w = p[i][2];
340 GLfloat h = p[i][3];
341
342 if ( e[i] ) {
343
344 glEnable( GL_TEXTURE_2D );
345 glEnable( GL_BLEND );
346 glBlendFunc( GL_DST_COLOR, GL_ZERO );
347 glColor4f( 1, 1, 1, 0.5f );
348 glBindTexture( GL_TEXTURE_2D, shade_tex );
349 glBegin( GL_TRIANGLE_STRIP );
350 glTexCoord2f( 0, 0 );
351 glVertex2f( x - ( w / 2 ), y - ( h / 2 ) );
352 //glVertex2f( x, y );
353 glTexCoord2f( 1, 0 );
354 glVertex2f( x + w + ( w / 2 ), y - ( h / 2 ) );
355 //glVertex2f( x + w, y );
356 glTexCoord2f( 0, 1 );
357 glVertex2f( x - ( w / 2 ), y + h + ( h / 2 ) );
358 //glVertex2f( x, y + h );
359 glTexCoord2f( 1, 1 );
360 glVertex2f( x + w + ( w / 2 ), y + h + ( h / 2 ) );
361 //glVertex2f( x + w, y + h );
362 glEnd();
363 glDisable( GL_BLEND );
364 glDisable( GL_TEXTURE_2D );
365 glColor3f( DARK_R, DARK_G, DARK_B );
366 } else {
367 glBegin( GL_TRIANGLE_STRIP );
368 glVertex2f( x, y );
369 glVertex2f( x + w, y );
370 glVertex2f( x, y + h );
371 glVertex2f( x + w, y + h );
372 glEnd();
373 }
374 }
375 glPopMatrix();
376
377 #ifdef DEBUG_FOG
378 glLoadIdentity();
379 glDisable( GL_BLEND );
380 glColor3f( 1, 1, 1 );
381 for ( int i = 0; i < pCount; i++ ) {
382 glBegin( GL_LINE_LOOP );
383 glVertex2f( p[i][0], p[i][1] );
384 glVertex2f( p[i][0], p[i][1] + p[i][3] );
385 glVertex2f( p[i][0] + p[i][2], p[i][1] + p[i][3] );
386 glVertex2f( p[i][0] + p[i][2], p[i][1] );
387 glEnd();
388 }
389 glEnable( GL_BLEND );
390 #endif
391
392 glEnable( GL_BLEND );
393 glEnable( GL_TEXTURE_2D );
394 glEnable( GL_DEPTH_TEST );
395 }
396
397 // FIXME: highest static point can be stored in the fog[][] struct
getHighestZ(int sx,int sy,int w,int h)398 int Fog::getHighestZ( int sx, int sy, int w, int h ) {
399 int z = 0;
400 for ( int x = sx; x < sx + w; x++ ) {
401 for ( int y = sy; y < sy + h; y++ ) {
402 Location *pos = map->getLocation( x, y, 0 );
403 if ( pos && pos->shape ) {
404 int zz = pos->z + pos->shape->getHeight();
405 if ( zz > z ) z = zz;
406 }
407 }
408 }
409 return z;
410 }
411
getScreenXY(GLdouble mapx,GLdouble mapy,GLdouble mapz,GLdouble * screenx,GLdouble * screeny)412 void Fog::getScreenXY( GLdouble mapx, GLdouble mapy, GLdouble mapz,
413 GLdouble *screenx, GLdouble *screeny ) {
414 GLdouble screenz;
415
416 double projection[16];
417 double modelview[16];
418 GLint viewport[4];
419
420 glGetDoublev( GL_PROJECTION_MATRIX, projection );
421 glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
422 glGetIntegerv( GL_VIEWPORT, viewport );
423
424 int res = gluProject( mapx, mapy, mapz,
425 modelview,
426 projection,
427 viewport,
428 screenx, screeny, &screenz );
429 *screeny = ( map->getAdapter()->getScreenHeight() - *screeny );
430 if ( !res ) {
431 *screenx = *screeny = 2000;
432 }
433 }
434
createOverlayTexture()435 void Fog::createOverlayTexture() {
436
437 float half = ( static_cast<float>( OVERLAY_SIZE ) - 0.5f ) / 2.0f;
438 int maxP = 90;
439 int minP = 75;
440
441 // create the dark texture
442 glGenTextures( 1, &overlay_tex );
443 for ( unsigned int i = 0; i < OVERLAY_SIZE; i++ ) {
444 for ( unsigned int j = 0; j < OVERLAY_SIZE; j++ ) {
445
446 float id = static_cast<float>( i ) - half;
447 float jd = static_cast<float>( j ) - half;
448
449 // the distance
450 float dist = sqrt( id * id + jd * jd );
451
452 // the distance as a percent of the max distance
453 float percent = dist / ( sqrt( half * half ) / 100.0f );
454
455 int r, g, b, a;
456 r = ER;
457 g = EG;
458 b = EB;
459 if ( percent < minP ) {
460 a = 0;
461 } else if ( percent >= maxP ) {
462 a = EA;
463 } else {
464 a = static_cast<int>( static_cast<float>( percent - minP ) *
465 ( static_cast<float>( EA ) / static_cast<float>( maxP - minP ) ) );
466 }
467 overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 0] = ( unsigned char )r;
468 overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 1] = ( unsigned char )g;
469 overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 2] = ( unsigned char )b;
470 overlay_data[i * OVERLAY_SIZE * 4 + j * 4 + 3] = ( unsigned char )a;
471 }
472 }
473 glBindTexture( GL_TEXTURE_2D, overlay_tex );
474 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
475 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
476 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
477 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
478 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
479 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
480 glTexImage2D( GL_TEXTURE_2D, 0, ( map->getPreferences()->getBpp() > 16 ? GL_RGBA : GL_RGBA4 ), OVERLAY_SIZE, OVERLAY_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, overlay_data );
481 gluBuild2DMipmaps( GL_TEXTURE_2D, ( map->getPreferences()->getBpp() > 16 ? GL_RGBA : GL_RGBA4 ), OVERLAY_SIZE, OVERLAY_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, overlay_data );
482 }
483
createShadeTexture()484 void Fog::createShadeTexture() {
485
486 float half = ( static_cast<float>( OVERLAY_SIZE ) - 0.5f ) / 2.0f;
487 int maxP = 90;
488 int minP = 70;
489
490 // create the dark texture
491 glGenTextures( 1, &shade_tex );
492 for ( unsigned int i = 0; i < OVERLAY_SIZE; i++ ) {
493 for ( unsigned int j = 0; j < OVERLAY_SIZE; j++ ) {
494
495 float id = static_cast<float>( i ) - half;
496 float jd = static_cast<float>( j ) - half;
497
498 // the distance
499 float dist = sqrt( id * id + jd * jd );
500
501 // the distance as a percent of the max distance
502 float percent = dist / ( sqrt( half * half ) / 100.0f );
503
504 int r, g, b;
505 if ( percent < minP ) {
506 r = SR;
507 g = SG;
508 b = SB;
509 } else if ( percent >= maxP ) {
510 r = 0xff;
511 g = 0xff;
512 b = 0xff;
513 } else {
514 r = SR + static_cast<int>( static_cast<float>( percent - minP ) * ( static_cast<float>( 0xff - SR ) / static_cast<float>( maxP - minP ) ) );
515 if ( r > 0xff )
516 r = 0xff;
517 g = SG + static_cast<int>( static_cast<float>( percent - minP ) * ( static_cast<float>( 0xff - SG ) / static_cast<float>( maxP - minP ) ) );
518 if ( g > 0xff )
519 g = 0xff;
520 b = SB + static_cast<int>( static_cast<float>( percent - minP ) * ( static_cast<float>( 0xff - SB ) / static_cast<float>( maxP - minP ) ) );
521 if ( b > 0xff )
522 b = 0xff;
523 }
524 shade_data[i * OVERLAY_SIZE * 3 + j * 3 + 0] = ( unsigned char )r;
525 shade_data[i * OVERLAY_SIZE * 3 + j * 3 + 1] = ( unsigned char )g;
526 shade_data[i * OVERLAY_SIZE * 3 + j * 3 + 2] = ( unsigned char )b;
527 }
528 }
529 glBindTexture( GL_TEXTURE_2D, shade_tex );
530 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
531 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
532 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
533 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
534 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
535 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
536 glTexImage2D( GL_TEXTURE_2D, 0, ( map->getPreferences()->getBpp() > 16 ? GL_RGB : GL_RGB5 ), OVERLAY_SIZE, OVERLAY_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, shade_data );
537 gluBuild2DMipmaps( GL_TEXTURE_2D, ( map->getPreferences()->getBpp() > 16 ? GL_RGB : GL_RGB5 ), OVERLAY_SIZE, OVERLAY_SIZE, GL_RGB, GL_UNSIGNED_BYTE, shade_data );
538 }
539
load(FogInfo * fogInfo)540 void Fog::load( FogInfo *fogInfo ) {
541 for ( int x = 0; x < MAP_WIDTH; x++ ) {
542 for ( int y = 0; y < MAP_DEPTH; y++ ) {
543 fog[x][y] = fogInfo->fog[x][y];
544 }
545 }
546 }
547
save(FogInfo * fogInfo)548 void Fog::save( FogInfo *fogInfo ) {
549 for ( int x = 0; x < MAP_WIDTH; x++ ) {
550 for ( int y = 0; y < MAP_DEPTH; y++ ) {
551 fogInfo->fog[x][y] = fog[x][y];
552 }
553 }
554 }
555