1 /*
2 * Seven Kingdoms: Ancient Adversaries
3 *
4 * Copyright 1997,1998 Enlight Software Ltd.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 //Filename : OWORLD_Z.CPP
22 //Description : Object ZoomMatrix
23
24 #include <math.h>
25 #include <OVGA.h>
26 #include <OSYS.h>
27 #include <OFONT.h>
28 #include <OMOUSE.h>
29 #include <OPOWER.h>
30 #include <OSTR.h>
31 #include <OSITE.h>
32 #include <OFIRM.h>
33 #include <OTOWN.h>
34 #include <OGAME.h>
35 #include <OUNIT.h>
36 #include <ONATION.h>
37 #include <OSPRITE.h>
38 #include <OBULLET.h>
39 #include <OPLANT.h>
40 #include <OTERRAIN.h>
41 #include <OWALLRES.h>
42 #include <OLIGHTN.h>
43 #include <ORAIN.h>
44 #include <OSNOW.h>
45 #include <OWORLD.h>
46 #include <OWEATHER.h>
47 #include <OFLAME.h>
48 #include <OGODRES.h>
49 #include <OU_GOD.h>
50 #include <OAUDIO.h>
51 #include <OHILLRES.h>
52 #include <OTORNADO.h>
53 #include <OSNOWG.h>
54 #include <OSNOWRES.h>
55 #include <OEXPMASK.h>
56 #include <OCOLTBL.h>
57 #include <OROCKRES.h>
58 #include <OROCK.h>
59 #include <OEFFECT.h>
60 #include <COLCODE.h>
61 #include <OANLINE.h>
62 #include <OFIRMDIE.h>
63 #include <OIMGRES.h>
64 #include "gettext.h"
65
66 //--------- Define static vars -----------//
67
68 //static int init_rain = 0; // reset on new game and load game
69 static Rain rain;
70 //static int rain_channel_id = 0; // reset on new game and load game
71 //static int wind_channel_id = 0; // reset on new game and load game
72 //static int fire_channel_id = 0; // reset on new game and load game
73 //static int last_fire_vol = 0; // reset on new game and load game
74 //static int init_lightning = 0; // reset on new game, save on save game
75 static YLightning lightning;
76 //static int init_snow = 0; // reset on new game and load game
77 static Snow snow;
78 //static short last_brightness = 0; // reset on new game and load game
79 //static int vibration = -1; // reset on new game, save on save game
80 //static short lightning_x1, lightning_y1, lightning_x2, lightning_y2; // save on save game
81 static int init_fire = -10; // reset on new game and load game
82
83 //-------- Declare static functions ---------//
84
85 static int sort_display_function( const void *a, const void *b );
86
87
88 //------- Define constant for object_type --------//
89
90 enum { OBJECT_UNIT,
91 OBJECT_POINTED_UNIT,
92 OBJECT_BULLET,
93 OBJECT_FIRM,
94 OBJECT_TOWN,
95 OBJECT_PLANT,
96 OBJECT_FIRE,
97 OBJECT_WALL,
98 OBJECT_TORNADO,
99 OBJECT_HILL,
100 OBJECT_ROCK,
101 OBJECT_EFFECT,
102 // ###### begin Gilbert 2/10 #######//
103 OBJECT_FIRM_DIE,
104 // ###### end Gilbert 2/10 #######//
105 };
106
107 enum { LAND_DISP_LAYER_MASK=1,
108 LAND_TOP_DISP_LAYER_MASK=2,
109 LAND_BOTTOM_DISP_LAYER_MASK=4,
110 AIR_DISP_LAYER_MASK=8,
111 };
112
113 //---------- Define struct DisplaySort ----------//
114
115 struct DisplaySort
116 {
117 char object_type;
118 short object_recno;
119 short object_y2;
120 short x_loc, y_loc;
121 };
122
123
124 //------------ begin of static function draw_unit_path_on_zoom_map -----------//
125 // ##### begin Gilbert 9/10 #######//
draw_unit_path_on_zoom_map(int displayLayer)126 static void draw_unit_path_on_zoom_map(int displayLayer)
127 // ##### end Gilbert 9/10 #######//
128 {
129 // ###### begin Gilbert 29/8 ######//
130 if( !(config.show_unit_path & 1) )
131 return;
132 // ###### end Gilbert 29/8 ######//
133
134 short nationRecno = nation_array.player_recno;
135
136 Unit *unitPtr;
137 int i, j, resultNodeCount, resultNodeRecno;
138 short lineFromX, lineFromY, lineToX, lineToY;
139 ResultNode *resultNode1, *resultNode2;
140
141 for(i=unit_array.size(); i>0; --i)
142 {
143 if(unit_array.is_deleted(i))
144 continue;
145
146 unitPtr = unit_array[i];
147 if(!unitPtr->is_visible())
148 continue;
149
150 if(!unitPtr->selected_flag)
151 continue;
152
153 // ####### begin Gilbert 11/9 #######//
154 if( !config.show_ai_info && nationRecno && !unitPtr->is_nation(nationRecno) )
155 continue;
156 // ####### end Gilbert 11/9 #######//
157
158 // ##### begin Gilbert 9/10 #######//
159 if( unitPtr->mobile_type == UNIT_LAND || unitPtr->mobile_type == UNIT_SEA )
160 {
161 if( !(displayLayer & LAND_DISP_LAYER_MASK) )
162 continue;
163 }
164 else if( unitPtr->mobile_type == UNIT_AIR )
165 {
166 if( !(displayLayer & AIR_DISP_LAYER_MASK) )
167 continue;
168 }
169 else
170 {
171 err_here();
172 continue;
173 }
174 // ##### end Gilbert 9/10 #######//
175
176 //--------------- draw unit's path ----------------//
177
178 resultNodeRecno = unitPtr->result_node_recno;
179 resultNodeCount = unitPtr->result_node_count;
180 if(!resultNodeCount || resultNodeRecno>resultNodeCount)
181 continue;
182
183 //-----------------------------------------------------------//
184 if(unitPtr->cur_x!=unitPtr->go_x || unitPtr->cur_y!=unitPtr->go_y)
185 {
186 lineFromX = unitPtr->go_x - world.zoom_matrix->top_x_loc*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2;
187 lineFromY = unitPtr->go_y - world.zoom_matrix->top_y_loc*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2;
188 lineToX = unitPtr->cur_x - world.zoom_matrix->top_x_loc*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2;
189 lineToY = unitPtr->cur_y - world.zoom_matrix->top_y_loc*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2;
190 anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY);
191 }
192
193 //-----------------------------------------------------------//
194 err_when(resultNodeRecno<1);
195 resultNode1 = unitPtr->result_node_array + resultNodeRecno - 1;
196 resultNode2 = resultNode1 + 1;
197 lineToX = (resultNode1->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2;
198 lineToY = (resultNode1->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2;
199 for(j=resultNodeRecno+1; j<=resultNodeCount; j++, resultNode1++, resultNode2++)
200 {
201 lineFromX = (resultNode2->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2;
202 lineFromY = (resultNode2->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2;
203 anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY);
204 lineToX = lineFromX;
205 lineToY = lineFromY;
206 }
207 }
208 }
209 //------------ end of static function draw_unit_path_on_zoom_map -----------//
210
211
212 //------------ begin of static function draw_unit_way_point_on_zoom_map -----------//
draw_unit_way_point_on_zoom_map()213 static void draw_unit_way_point_on_zoom_map()
214 {
215 short nationRecno = nation_array.player_recno;
216
217 Unit *unitPtr;
218 int i, j, resultNodeCount;
219 short lineFromX, lineFromY, lineToX, lineToY;
220 ResultNode *resultNode1, *resultNode2;
221 // ##### begin Gilbert 12/11 #######//
222 char *chPtr = image_icon.get_ptr("WAYPOINT");
223 short chOffsetX = - (*(short *)chPtr / 2);
224 short chOffsetY = - (*(1+(short *)chPtr) / 2);
225 // ##### end Gilbert 12/11 #######//
226
227 for(i=unit_array.size(); i>0; --i)
228 {
229 if(unit_array.is_deleted(i))
230 continue;
231
232 unitPtr = unit_array[i];
233 if(!unitPtr->is_visible())
234 continue;
235
236 if(!unitPtr->selected_flag)
237 continue;
238
239 if( !config.show_ai_info && nationRecno && !unitPtr->is_nation(nationRecno) )
240 continue;
241
242 if(unitPtr->way_point_count)
243 {
244 resultNodeCount = unitPtr->way_point_count;
245 resultNode1 = unitPtr->way_point_array;
246 // ##### begin Gilbert 12/11 #######//
247 // char *chPtr = image_icon.get_ptr("WAYPOINT");
248 lineToX = (resultNode1->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2;
249 lineToY = (resultNode1->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2;
250 world.zoom_matrix->put_bitmap_clip(lineToX+chOffsetX, lineToY+chOffsetY, chPtr);
251 // ##### begin Gilbert 12/11 #######//
252
253 if(resultNodeCount>1)
254 {
255 resultNode2 = resultNode1+1;
256 for(j=1; j<resultNodeCount; j++, resultNode1++, resultNode2++)
257 {
258 lineFromX = (resultNode2->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2;
259 lineFromY = (resultNode2->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2;
260 anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY, 0, 1);
261 lineToX = lineFromX;
262 lineToY = lineFromY;
263 // ##### begin Gilbert 12/11 #######//
264 world.zoom_matrix->put_bitmap_clip(lineToX+chOffsetX, lineToY+chOffsetY, chPtr);
265 // ##### begin Gilbert 12/11 #######//
266 }
267 }
268 }
269 }
270 }
271 //------------ end of static function draw_unit_way_point_on_zoom_map -----------//
272
273
274 //-------- Begin of function ZoomMatrix::ZoomMatrix ----------//
275
ZoomMatrix()276 ZoomMatrix::ZoomMatrix() : land_disp_sort_array(sizeof(DisplaySort),100),
277 air_disp_sort_array(sizeof(DisplaySort),50),
278 land_top_disp_sort_array(sizeof(DisplaySort), 40),
279 land_bottom_disp_sort_array(sizeof(DisplaySort), 20)
280 {
281 init( ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2,
282 ZOOM_WIDTH, ZOOM_HEIGHT,
283 ZOOM_LOC_WIDTH, ZOOM_LOC_HEIGHT, 0 ); // 0-don't create a background buffer
284 }
285 //---------- End of function ZoomMatrix::ZoomMatrix ----------//
286
287
288 //---------- Begin of function ZoomMatrix::init_para ------------//
init_para()289 void ZoomMatrix::init_para()
290 {
291 init_rain = 0;
292 // #### begin Gilbert 7/10 ######//
293 rain.clear();
294 rain.stop_rain();
295 // #### end Gilbert 7/10 ######//
296 rain_channel_id = 0;
297 wind_channel_id = 0;
298 fire_channel_id = 0;
299 last_fire_vol = 0;
300 init_lightning = 0;
301 init_snow = 0;
302 last_brightness = 0;
303 vibration = -1;
304 }
305 //---------- End of function ZoomMatrix::init_para ----------//
306
307
308 //---------- Begin of function ZoomMatrix::draw ------------//
309 //
310 // Draw world map
311 //
draw()312 void ZoomMatrix::draw()
313 {
314 int i=0, x, y, xLoc, yLoc, dispPower;
315 Location* locPtr;
316 char* nationColorArray = nation_array.nation_power_color_array;
317
318 int maxXLoc = top_x_loc + disp_x_loc; // divide by 2 for world_info
319 int maxYLoc = top_y_loc + disp_y_loc;
320
321 dispPower = (world.map_matrix->map_mode == MAP_MODE_POWER &&
322 world.map_matrix->power_mode ) ||
323 power.command_id == COMMAND_BUILD_FIRM ||
324 power.command_id == COMMAND_SETTLE;
325
326 sys.yield();
327
328 //----------------------------------------------------//
329
330 int nationRecno, borderColor;
331
332 for( y=image_y1,yLoc=top_y_loc ; yLoc<maxYLoc ; yLoc++, y+=loc_height )
333 {
334 locPtr = get_loc(top_x_loc,yLoc);
335
336 long snowSeed = (snow_ground_array.snow_pattern << 16) + (yLoc << 8);
337
338 for( x=image_x1,xLoc=top_x_loc ; xLoc<maxXLoc ; xLoc++, x+=loc_width, locPtr++ )
339 {
340 if( locPtr->explored() ) // only draw if the location has been explored
341 {
342 //---------- draw terrain bitmap -----------//
343
344 vga_back.put_bitmap_32x32( x, y, terrain_res[locPtr->terrain_id]->bitmap_ptr );
345 char *overlayBitmap = terrain_res[locPtr->terrain_id]->get_bitmap(sys.frame_count /4);
346 if( overlayBitmap)
347 vga_back.put_bitmap_trans_decompress( x, y, overlayBitmap);
348
349 #ifdef DEBUG
350 if(debug2_enable_flag)
351 {
352 if(locPtr->is_coast())
353 {
354 VgaBuf *activeBufBackup = Vga::active_buf;
355 Vga::active_buf = &vga_back;
356 font_std.put( x+24, y+20, terrain_res[locPtr->terrain_id]->average_type);
357 Vga::active_buf = activeBufBackup;
358 }
359 }
360 #endif
361
362 // --------- draw dirt block --------//
363 if( locPtr->has_dirt() )
364 {
365 dirt_array[locPtr->dirt_recno()]->draw_block(xLoc,yLoc);
366 }
367
368 if(terrain_res[locPtr->terrain_id]->can_snow() )
369 {
370 if( config.snow_ground==1 && snow_ground_array.snow_thick > 0)
371 {
372 vga_back.snow_32x32(x,y, snowSeed+xLoc, 0xffff - snow_ground_array.snow_thick);
373 }
374
375 if( config.snow_ground==2)
376 {
377 int snowMapId = snow_ground_array.has_snow(xLoc,yLoc);
378 if( snowMapId )
379 {
380 snow_res[snowMapId]->draw_at(xLoc*ZOOM_LOC_WIDTH+ZOOM_LOC_WIDTH/2, yLoc*ZOOM_LOC_HEIGHT+ZOOM_LOC_HEIGHT/2);
381 }
382 }
383 }
384
385 // --------- draw hill square --------//
386 if( locPtr->has_hill() )
387 {
388 if( locPtr->hill_id2())
389 hill_res[locPtr->hill_id2()]->draw(xLoc,yLoc,1);
390 hill_res[locPtr->hill_id1()]->draw(xLoc, yLoc,1);
391 }
392
393 //---------- if in power map mode -----------//
394
395 if( dispPower && (nationRecno=locPtr->power_nation_recno) > 0 )
396 {
397 vga_back.pixelize_32x32( x, y, nationColorArray[nationRecno] );
398
399 borderColor = nationColorArray[nationRecno] + 1;
400
401 if( yLoc==0 || get_loc(xLoc, yLoc-1)->power_nation_recno!=nationRecno )
402 vga_back.bar( x, y, x+31, y, borderColor );
403
404 if( yLoc==MAX_WORLD_Y_LOC-1 || get_loc(xLoc, yLoc+1)->power_nation_recno!=nationRecno )
405 vga_back.bar( x, y+31, x+31, y+31, borderColor );
406
407 if( xLoc==0 || get_loc(xLoc-1, yLoc)->power_nation_recno!=nationRecno )
408 vga_back.bar( x, y, x, y+31, borderColor );
409
410 if( xLoc==MAX_WORLD_X_LOC-1 || get_loc(xLoc+1, yLoc)->power_nation_recno!=nationRecno )
411 vga_back.bar( x+31, y, x+31, y+31, borderColor );
412 }
413
414 //--------- draw raw material icon ---------//
415
416 if( locPtr->has_site() && locPtr->walkable(3) ) // don't display if a building/object has already been built on the location
417 site_array[locPtr->site_recno()]->draw(x, y);
418
419 //----- draw grids, for debugging only -----//
420
421 #ifdef DEBUG
422 if(debug2_enable_flag)
423 {
424 vga_back.bar( x, y, x+31, y, V_WHITE );
425 vga_back.bar( x, y, x, y+31, V_WHITE );
426
427 // display x, y location
428 if(!(xLoc%5) && !(yLoc%5))
429 {
430 VgaBuf *activeBufBackup = Vga::active_buf;
431 Vga::active_buf = &vga_back;
432 font_std.put( x+4, y+3, xLoc );
433 font_std.put( x+4, y+15, yLoc );
434 Vga::active_buf = activeBufBackup;
435 }
436 }
437 #endif
438 }
439 }
440 }
441
442 sys.yield();
443
444 //---------------------------------------------------//
445
446 if( save_image_buf )
447 {
448 vga_back.read_bitmap( image_x1, image_y1, image_x2, image_y2, save_image_buf );
449 just_drawn_flag = 1;
450 }
451 }
452 //------------ End of function ZoomMatrix::draw ------------//
453
454
455 //---------- Begin of function ZoomMatrix::draw_white_site ------------//
456 //
draw_white_site()457 void ZoomMatrix::draw_white_site()
458 {
459 int i=0, x, y, xLoc, yLoc;
460 Location* locPtr;
461
462 int maxXLoc = top_x_loc + disp_x_loc; // divide by 2 for world_info
463 int maxYLoc = top_y_loc + disp_y_loc;
464
465 //------- draw occupied locations in whie ---------//
466
467 for( y=image_y1,yLoc=top_y_loc ; yLoc<maxYLoc ; yLoc++, y+=loc_height )
468 {
469 locPtr = get_loc(top_x_loc,yLoc);
470
471 for( x=image_x1,xLoc=top_x_loc ; xLoc<maxXLoc ; xLoc++, x+=loc_width, locPtr++ )
472 {
473 if(locPtr->has_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA) || locPtr->has_unit(UNIT_AIR))
474 vga_back.bar( x, y, x+31, y+31, V_WHITE );
475 }
476 }
477 }
478 //------------ End of function ZoomMatrix::draw_white_site ------------//
479
480
481 //---------- Begin of function ZoomMatrix::draw_frame -----------//
482 //
draw_frame()483 void ZoomMatrix::draw_frame()
484 {
485 draw_objects();
486
487 draw_weather_effects();
488
489 draw_build_marker();
490
491 if(config.blacken_map && config.fog_of_war)
492 blacken_fog_of_war();
493
494 else if( !config.explore_whole_map )
495 blacken_unexplored();
496
497 disp_text();
498 }
499 //----------- End of function ZoomMatrix::draw_frame ------------//
500
501
502 //---------- Begin of function ZoomMatrix::draw_weather_effects -----------//
503 //
draw_weather_effects()504 void ZoomMatrix::draw_weather_effects()
505 {
506 //---------- Earthquake -----------//
507
508 if( weather.is_quake() )
509 {
510 if(vibration == -1)
511 {
512 // start of an earthquake
513 vibration = weather.quake_rate(top_x_loc+disp_x_loc/2, top_y_loc+disp_y_loc/2)*16/100;
514 if( config.sound_effect_flag && config.earthquake_audio)
515 {
516 RelVolume r(config.earthquake_volume,0);
517 audio.play_long_wav( DIR_SOUND"QUAKE.WAV", DsVolume(r) );
518 }
519 }
520 int vPitch = vga_back.buf_pitch();
521 char *destBitmap = vga_back.buf_ptr() + ZOOM_Y1 * vPitch + ZOOM_X1;
522 char *srcBitmap = destBitmap + vibration * vPitch;
523 int lineCount = ZOOM_HEIGHT - vibration;
524
525 // shift back buffer up
526
527 if( vibration )
528 {
529 if( config.earthquake_visual)
530 {
531 for(int lineRun = 0; lineRun < lineCount; ++lineRun)
532 {
533 memcpy(destBitmap, srcBitmap, ZOOM_WIDTH);
534 destBitmap += vPitch;
535 srcBitmap += vPitch;
536 }
537 }
538 vibration = 0;
539 }
540 else
541 {
542 vibration = weather.quake_rate(top_x_loc+disp_x_loc/2, top_y_loc+disp_y_loc/2)*16/100;
543 }
544 }
545 else
546 {
547 vibration = -1;
548 }
549
550
551 //---------- raining --------//
552
553 short newRainScale = weather.rain_scale();
554
555 if( newRainScale != init_rain )
556 {
557 // BUGHERE : did not handle, wind change (direction/speed) during a rain
558 if( newRainScale)
559 {
560 rain.start_rain(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, newRainScale,
561 weather.wind_speed()*sin(weather.wind_direct_rad())/100.0);
562
563 // turn on rain noise
564
565 int relVolume = config.rain_volume + newRainScale;
566 if( relVolume > 100)
567 relVolume = 100;
568
569 if( rain_channel_id == 0) // from no rain to rain
570 {
571 if( config.sound_effect_flag && config.rain_audio)
572 {
573 RelVolume r(relVolume,0);
574 rain_channel_id = audio.play_loop_wav(DIR_SOUND"RAIN.WAV",11008*2, DsVolume(r));
575 }
576 }
577 else
578 {
579 // changing rain
580 if( config.sound_effect_flag && config.rain_audio)
581 {
582 RelVolume r(relVolume,0);
583 audio.volume_loop_wav(rain_channel_id, DsVolume(r));
584 }
585 else
586 {
587 // can't stop rain audio immediately
588 // but at least stop it when rain change
589 audio.stop_loop_wav(rain_channel_id);
590 rain_channel_id = 0;
591 }
592
593 }
594
595 }
596 else
597 {
598 // rain stop, rain sound fade out
599 rain.stop_rain();
600 if( rain_channel_id )
601 {
602 audio.fade_out_loop_wav(rain_channel_id, 10);
603 }
604 }
605 init_rain = newRainScale;
606 }
607 else
608 {
609 // rain stopped, check rain sound fade out
610 if( newRainScale == 0 && rain_channel_id )
611 {
612 DsVolume dsVolume(audio.get_loop_wav_volume(rain_channel_id));
613 AbsVolume absVolume(dsVolume);
614 if( absVolume.abs_vol < 10 )
615 {
616 audio.stop_loop_wav(rain_channel_id);
617 rain_channel_id = 0;
618 }
619 }
620 }
621
622 // ##### begin Gilbert 6/9 #######//
623 if( config.frame_speed > 0)
624 {
625 rain.new_drops();
626 if( config.rain_visual)
627 {
628 rain.draw_step(&vga_back);
629 }
630 }
631 // ##### end Gilbert 6/9 #######//
632
633
634 //---------- Lightning -----------//
635 // world.lightning_signal == 0 (no lightning)
636 // world.lightning_signal == 110, 109 (ready lightning)
637 // 108, 107, 106, 105 (flashing), Sound effect start on 6
638 // 104, 103, 102, 101 (rest, decaying lighting effect )
639 // 100 (decrease randomly)
640 // 99 - 1 (rest states)
641 // see world.process
642
643 unsigned long mRandom = misc.get_random_seed();
644 if( world.lightning_signal >= 105 && world.lightning_signal <= 108)
645 {
646 if( !init_lightning )
647 {
648 // play sound
649 if( world.lightning_signal == 108 && config.sound_effect_flag && config.lightning_audio)
650 {
651 RelVolume r(config.lightning_volume,0);
652 audio.play_long_wav(DIR_SOUND"THUNDER.WAV", DsVolume(r));
653 }
654
655 // find the starting and ending point of the lightning
656 lightning_x1 = Lightning::bound_x1 + 20 + short(mRandom % (Lightning::bound_x2-Lightning::bound_x1 - 40));
657 lightning_y1 = Lightning::bound_y1 - 50;
658 lightning_x2 = Lightning::bound_x1 + 10 + short(mRandom % (Lightning::bound_x2-Lightning::bound_x1 - 20));
659 lightning_y2 = (Lightning::bound_y1+Lightning::bound_y2) / 2 +
660 short(mRandom % ( (Lightning::bound_y2-Lightning::bound_y1) / 2));
661 init_lightning = 1;
662 }
663
664 lightning.init( lightning_x1, lightning_y1, lightning_x2, lightning_y2, 8);
665 if( config.lightning_visual)
666 lightning.draw_section(&vga_back, (109-world.lightning_signal)/4.0);
667 }
668 else
669 {
670 init_lightning = 0;
671 }
672
673 //------------ snowing ------------//
674 short snowScale = weather.snow_scale();
675 if( snowScale > 0 && init_snow == 0)
676 {
677 long backupSeed = misc.get_random_seed();
678
679 // start of snow
680 snow.set_bound(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2);
681 snow.init(weather.wind_speed()*sin(weather.wind_direct_rad())/200.0,
682 snowScale+2);
683 if( config.sound_effect_flag && config.snow_audio )
684 {
685 // audio.play_wav("SNOW", config.snow_volume);
686 }
687 }
688 // ###### begin Gilbert 6/9 #######//
689 if( snowScale > 0 && config.snow_visual && config.frame_speed > 0)
690 snow.draw_step(&vga_back);
691 // ###### end Gilbert 6/9 #######//
692 init_snow = snowScale;
693
694 //------------ brightness, effect of lightning and cloud -------//
695 short newBrightness;
696 short maxBrightness = config.lightning_brightness;
697 if( config.lightning_visual && init_lightning > 107 )
698 {
699 newBrightness = -maxBrightness;
700 }
701 else if( config.lightning_visual && init_lightning >= 104 && init_lightning <= 107)
702 {
703 newBrightness = maxBrightness;
704 }
705 else if( config.lightning_visual && init_lightning >= 101 && init_lightning <= 103)
706 {
707 newBrightness = (init_lightning-100) * maxBrightness / 4;
708 }
709 else
710 {
711 newBrightness = -weather.cloud() * config.cloud_darkness ;
712 }
713 if( newBrightness != last_brightness )
714 {
715 vga.adjust_brightness(newBrightness);
716 last_brightness = newBrightness;
717 }
718
719 // ------------- wind sound ----------//
720 int windSpeed = weather.wind_speed();
721 if( windSpeed >= 20)
722 {
723 int relVolume = config.wind_volume + 5 + windSpeed/4;
724 if( relVolume > 100)
725 relVolume = 100;
726 if( wind_channel_id == 0)
727 {
728 if( config.sound_effect_flag && config.wind_audio )
729 {
730 // ###### begin Gilbert 6/8 #######//
731 // wind_channel_id = audio.play_loop_wav(DIR_SOUND"WIND.WAV",0, relVolume);
732 RelVolume r(relVolume,0);
733 wind_channel_id = audio.play_loop_wav(DIR_SOUND"WIND.WAV",25088*2, DsVolume(r)); // 25088 samples, 8-bit stereo, so *2
734 // ###### end Gilbert 6/8 #######//
735 }
736 }
737 else
738 {
739 if( config.wind_audio)
740 {
741 RelVolume r(relVolume,0);
742 audio.volume_loop_wav(wind_channel_id, DsVolume(r));
743 }
744 else
745 {
746 audio.stop_loop_wav(wind_channel_id);
747 wind_channel_id = 0;
748 }
749 }
750 }
751 else
752 {
753 if( wind_channel_id )
754 {
755 if( !audio.is_loop_wav_fading(wind_channel_id) )
756 {
757 audio.fade_out_loop_wav(wind_channel_id, 5);
758 }
759 else
760 {
761 DsVolume dsVolume = audio.get_loop_wav_volume(wind_channel_id);
762 AbsVolume absVolume(dsVolume);
763 if( absVolume.abs_vol < 5 )
764 {
765 audio.stop_loop_wav(wind_channel_id);
766 wind_channel_id =0 ;
767 }
768 }
769 }
770 }
771
772 }
773 //----------- End of function ZoomMatrix::draw_weather_effects ------------//
774
775
776 //---------- Begin of function ZoomMatrix::draw_build_marker -----------//
777 //
draw_build_marker()778 void ZoomMatrix::draw_build_marker()
779 {
780 if( !(mouse.cur_x >= ZOOM_X1 && mouse.cur_x <= ZOOM_X2 && // if the mouse is inside the zoom area
781 mouse.cur_y >= ZOOM_Y1 && mouse.cur_y <= ZOOM_Y2) )
782 {
783 return;
784 }
785
786 // ##### begin Gilbert 24/10 #######//
787 if( power.win_opened )
788 return;
789 // ##### end Gilbert 24/10 #######//
790
791 //------- COMMAND_GOD_CAST_POWER --------//
792
793 else if( power.command_id == COMMAND_GOD_CAST_POWER )
794 {
795 draw_god_cast_range();
796 return;
797 }
798
799 //----------------------------------------------//
800
801 int xLoc = (mouse.cur_x-ZOOM_X1)/ZOOM_LOC_WIDTH;
802 int yLoc = (mouse.cur_y-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
803 int locWidth, locHeight, validAction;
804 Location* locPtr = world.get_loc(top_x_loc+xLoc, top_y_loc+yLoc);
805
806 //------- if it's in firm building mode now ----//
807
808 if( power.command_id == COMMAND_BUILD_FIRM )
809 {
810 FirmInfo* firmInfo = firm_res[power.command_para];
811
812 locWidth = firmInfo->loc_width;
813 locHeight = firmInfo->loc_height;
814
815 validAction = world.can_build_firm( top_x_loc+xLoc, top_y_loc+yLoc, power.command_para, unit_array.selected_recno );
816 }
817
818 //------- if it's in settling mode now ----//
819
820 else if( power.command_id == COMMAND_SETTLE && unit_array.selected_recno )
821 {
822 // assign to an existing town
823
824 Unit* selectedUnit = unit_array[ unit_array.selected_recno ];
825
826 if( locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno == selectedUnit->nation_recno )
827 return; // don't draw the settling mask.
828
829 locWidth = STD_TOWN_LOC_WIDTH;
830 locHeight = STD_TOWN_LOC_HEIGHT;
831
832 validAction = world.can_build_town( top_x_loc+xLoc, top_y_loc+yLoc, unit_array.selected_recno );
833 }
834
835 //------- COMMAND_BUILD_WALL --------//
836
837 else if( power.command_id == COMMAND_BUILD_WALL )
838 {
839 // see also World::build_wall_tile
840 locWidth = 1;
841 locHeight = 1;
842 Location *locPtr;
843
844 validAction = world.can_build_wall(top_x_loc+xLoc, top_y_loc+yLoc, nation_array.player_recno)
845 || ( (locPtr=get_loc(top_x_loc+xLoc, top_y_loc+yLoc))->is_wall() && locPtr->is_wall_destructing() &&
846 world.can_destruct_wall(top_x_loc+xLoc, top_y_loc+yLoc, nation_array.player_recno) );
847 }
848
849 //------- COMMAND_DESTRUCT_WALL --------//
850
851 else if( power.command_id == COMMAND_DESTRUCT_WALL )
852 {
853 locWidth = 1;
854 locHeight = 1;
855 // see also World::destruct_wall_tile
856 validAction = world.can_destruct_wall(top_x_loc+xLoc, top_y_loc+yLoc, nation_array.player_recno)
857 && get_loc(top_x_loc+xLoc, top_y_loc+yLoc)->is_wall_creating() ;
858 }
859
860 else
861 return;
862
863 //---------- draw an highlight area -----------//
864
865 int x1 = ZOOM_X1 + xLoc * ZOOM_LOC_WIDTH;
866 int y1 = ZOOM_Y1 + yLoc * ZOOM_LOC_HEIGHT;
867 int x2 = ZOOM_X1 + (xLoc+locWidth) * ZOOM_LOC_WIDTH -1;
868 int y2 = ZOOM_Y1 + (yLoc+locHeight) * ZOOM_LOC_HEIGHT-1;
869
870 int pixelColor;
871
872 if( validAction )
873 pixelColor = anim_line.get_series_color_array(-1)[2];
874 else
875 pixelColor = V_BLACK;
876
877 vga_back.pixelize( x1, y1, MIN(x2,ZOOM_X2), MIN(y2,ZOOM_Y2), pixelColor );
878
879 //------- draw lines connected to towns and firms ---------//
880
881 if( validAction )
882 {
883 if( power.command_id==COMMAND_BUILD_FIRM )
884 {
885 world.draw_link_line( power.command_para, 0, top_x_loc+xLoc, top_y_loc+yLoc,
886 top_x_loc+xLoc+locWidth-1, top_y_loc+yLoc+locHeight-1 );
887 }
888 else if( power.command_id==COMMAND_SETTLE )
889 {
890 world.draw_link_line( 0, 0, top_x_loc+xLoc, top_y_loc+yLoc,
891 top_x_loc+xLoc+locWidth-1, top_y_loc+yLoc+locHeight-1 );
892 }
893 }
894 }
895 //----------- End of function ZoomMatrix::draw_build_marker ------------//
896
897
898 //---------- Begin of function ZoomMatrix::draw_god_cast_range -----------//
899 //
draw_god_cast_range()900 void ZoomMatrix::draw_god_cast_range()
901 {
902 #define GOD_CAST_RANGE_COLOR V_WHITE
903
904 int xLoc, yLoc, centerY, t;
905 int x1, y1, x2, y2;
906
907 Unit* unitPtr = unit_array[power.command_unit_recno];
908 GodInfo* godInfo = god_res[ ((UnitGod*)unitPtr)->god_id ];
909
910 xLoc = (mouse.cur_x-ZOOM_X1)/ZOOM_LOC_WIDTH;
911 yLoc = (mouse.cur_y-ZOOM_Y1)/ZOOM_LOC_HEIGHT;
912
913 int xLoc1 = xLoc - godInfo->cast_power_range + 1;
914 int yLoc1 = yLoc - godInfo->cast_power_range + 1;
915 int xLoc2 = xLoc + godInfo->cast_power_range - 1;
916 int yLoc2 = yLoc + godInfo->cast_power_range - 1;
917
918 centerY = (yLoc1+yLoc2) / 2;
919
920 //----- pixelize the area within which the power can casted ----//
921
922 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
923 {
924 t=abs(yLoc-centerY)/2;
925
926 for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++ )
927 {
928 if( xLoc>=0 && xLoc<MAX_WORLD_X_LOC &&
929 yLoc>=0 && yLoc<MAX_WORLD_Y_LOC )
930 {
931 x1 = ZOOM_X1 + xLoc * ZOOM_LOC_WIDTH;
932 y1 = ZOOM_Y1 + yLoc * ZOOM_LOC_HEIGHT;
933 x2 = ZOOM_X1 + (xLoc+1) * ZOOM_LOC_WIDTH -1;
934 y2 = ZOOM_Y1 + (yLoc+1) * ZOOM_LOC_HEIGHT-1;
935
936 vga_back.pixelize( x1, y1, MIN(x2,ZOOM_X2), MIN(y2,ZOOM_Y2), GOD_CAST_RANGE_COLOR );
937 }
938 }
939 }
940 }
941 //----------- End of function ZoomMatrix::draw_god_cast_range ------------//
942
943
944 //---------- Begin of function ZoomMatrix::disp_text -----------//
945 //
946 // Function for displaying town names and spy indicator.
947 //
disp_text()948 void ZoomMatrix::disp_text()
949 {
950 //------- towns -------//
951
952 int y, dispSpy;
953
954 if( config.disp_town_name || config.disp_spy_sign )
955 {
956 Town* townPtr;
957
958 for( int i=town_array.size() ; i>0 ; i-- )
959 {
960 if( town_array.is_deleted(i) )
961 continue;
962
963 townPtr = town_array[i];
964
965 if( !world.get_loc(townPtr->center_x, townPtr->center_y)->explored() )
966 continue;
967
968 y = (townPtr->abs_y1+townPtr->abs_y2)/2;
969
970 dispSpy = config.disp_spy_sign && townPtr->has_player_spy();
971
972 if( config.disp_town_name && dispSpy )
973 y-=7;
974
975 if( config.disp_town_name )
976 {
977 String str(townPtr->town_name());
978
979 put_center_text( (townPtr->abs_x1+townPtr->abs_x2)/2, y, str );
980
981 y+=14;
982 }
983
984 if( dispSpy )
985 put_center_text( (townPtr->abs_x1+townPtr->abs_x2)/2, y, _("(Spy)") );
986 }
987 }
988
989 //------ firms -------//
990
991 if( config.disp_spy_sign )
992 {
993 Firm* firmPtr;
994
995 for( int i=firm_array.size() ; i>0 ; i-- )
996 {
997 if( firm_array.is_deleted(i) )
998 continue;
999
1000 firmPtr = firm_array[i];
1001
1002 if( firmPtr->player_spy_count )
1003 {
1004 put_center_text( (firmPtr->abs_x1+firmPtr->abs_x2)/2,
1005 (firmPtr->abs_y1+firmPtr->abs_y2)/2, _("(Spy)") );
1006 }
1007 }
1008 }
1009 }
1010 //----------- End of function ZoomMatrix::disp_text ------------//
1011
1012
1013 //---------- Begin of function ZoomMatrix::put_center_text -----------//
1014 //
1015 // <int> x, y - center of the absolute position where the text should be put.
1016 // <char*> str - the display string.
1017 //
put_center_text(int x,int y,const char * str)1018 void ZoomMatrix::put_center_text(int x, int y, const char* str)
1019 {
1020 const unsigned int TEMP_BUFFER_SIZE = 0x2000;
1021 char tempBuffer[TEMP_BUFFER_SIZE];
1022 short w = font_news.text_width(str);
1023 // ###### begin Gilbert 15/10 #######//
1024 // short h = font_news.text_height();
1025 short h = font_news.max_font_height;
1026 // ###### end Gilbert 15/10 #######//
1027
1028 if( w * h + 2*sizeof(short) <= TEMP_BUFFER_SIZE )
1029 {
1030 char *bufferPtr = tempBuffer;
1031 *(short *)bufferPtr = w;
1032 bufferPtr += sizeof(short);
1033 *(short *)bufferPtr = h;
1034 bufferPtr += sizeof(short);
1035 memset( bufferPtr, TRANSPARENT_CODE, w * h );
1036 font_news.put_to_buffer(bufferPtr, w, 0, 0, str);
1037
1038 // test clipping against ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2
1039 int x1 = x - World::view_top_x - w / 2 ;
1040 int x2 = x1 + w - 1;
1041 int y1 = y - World::view_top_y - h / 2;
1042 int y2 = y1 + h - 1;
1043 if( x1 < ZOOM_X2 && x2 >= 0 && y1 < ZOOM_HEIGHT && y2 >= 0)
1044 {
1045 if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
1046 {
1047 vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, tempBuffer,
1048 MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1);
1049 }
1050 else
1051 {
1052 vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, tempBuffer );
1053 }
1054 }
1055 }
1056 }
1057 //----------- End of function ZoomMatrix::put_center_text ------------//
1058
1059
1060 //---------- Begin of function ZoomMatrix::blacken_unexplored -----------//
1061 //
blacken_unexplored()1062 void ZoomMatrix::blacken_unexplored()
1063 {
1064 //----------- black out unexplored area -------------//
1065
1066 int leftLoc = top_x_loc;
1067 int topLoc = top_y_loc;
1068 int rightLoc = leftLoc + disp_x_loc - 1;
1069 int bottomLoc = topLoc + disp_y_loc - 1;
1070 int scrnY, scrnX; // screen coordinate
1071 int x, y; // x,y Location
1072 Location *thisRowLoc, *northRowLoc, *southRowLoc;
1073
1074 scrnY = ZOOM_Y1;
1075 for( y = topLoc; y <= bottomLoc; ++y, scrnY += ZOOM_LOC_HEIGHT)
1076 {
1077 thisRowLoc = get_loc(leftLoc, y);
1078 northRowLoc = y > 0 ? get_loc(leftLoc, y-1) : thisRowLoc;
1079 southRowLoc = y+1 < max_y_loc ? get_loc(leftLoc, y+1): thisRowLoc;
1080
1081 // load north bit into bit0, north west bit into bit 1
1082 int northRow = northRowLoc->explored() ? 1 : 0;
1083 int thisRow = thisRowLoc->explored() ? 1 : 0;
1084 int southRow = southRowLoc->explored() ? 1 : 0;
1085
1086 if( leftLoc > 0)
1087 {
1088 northRow |= (northRowLoc-1)->explored() ? 2 : 0;
1089 thisRow |= (thisRowLoc -1)->explored() ? 2 : 0;
1090 southRow |= (southRowLoc-1)->explored() ? 2 : 0;
1091 }
1092 else
1093 {
1094 // replicate bit 0 to bit 1;
1095 northRow *= 3;
1096 thisRow *= 3;
1097 southRow *= 3;
1098 }
1099
1100 scrnX = ZOOM_X1;
1101 for( x = leftLoc; x <= rightLoc; ++x, scrnX += ZOOM_LOC_WIDTH )
1102 {
1103 if( x+1 < max_x_loc)
1104 {
1105 northRow = (northRow << 1) | ((++northRowLoc)->explored() ? 1 : 0);
1106 thisRow = (thisRow << 1) | ((++thisRowLoc )->explored() ? 1 : 0);
1107 southRow = (southRow << 1) | ((++southRowLoc)->explored() ? 1 : 0);
1108 }
1109 else
1110 {
1111 // replicate bit 1
1112 northRow = (northRow << 1) | (northRow & 1);
1113 thisRow = (thisRow << 1) | (thisRow & 1);
1114 southRow = (southRow << 1) | (southRow & 1);
1115 }
1116
1117 // optional
1118 // northRow &= 7;
1119 // thisRow &= 7;
1120 // southRow &= 7;
1121
1122 // ---------- Draw mask to vgabuf --------//
1123
1124 if( thisRow & 2) // center square
1125 {
1126 explored_mask.draw(scrnX, scrnY, northRow, thisRow, southRow);
1127 }
1128 else
1129 {
1130 vga_back.black_32x32(scrnX, scrnY);
1131 }
1132 }
1133 }
1134 }
1135 //----------- End of function ZoomMatrix::blacken_unexplored ------------//
1136
1137
1138 //---------- Begin of function ZoomMatrix::blacken_fog_of_war -----------//
1139 //
blacken_fog_of_war()1140 void ZoomMatrix::blacken_fog_of_war()
1141 {
1142 int leftLoc = top_x_loc;
1143 int topLoc = top_y_loc;
1144 int rightLoc = leftLoc + disp_x_loc - 1;
1145 int bottomLoc = topLoc + disp_y_loc - 1;
1146 int scrnY, scrnX; // screen coordinate
1147 int x, y; // x,y Location
1148 Location *thisRowLoc, *northRowLoc, *southRowLoc;
1149
1150 if( config.fog_mask_method == 1)
1151 {
1152 // use fast method
1153 scrnY = ZOOM_Y1;
1154 for( y = topLoc; y <= bottomLoc; ++y, scrnY += ZOOM_LOC_HEIGHT)
1155 {
1156 thisRowLoc = get_loc(leftLoc,y);
1157 scrnX = ZOOM_X1;
1158 for( x = leftLoc; x <= rightLoc; ++x, scrnX += ZOOM_LOC_WIDTH, ++thisRowLoc )
1159 {
1160 if( !thisRowLoc->explored() )
1161 {
1162 vga_back.bar(scrnX, scrnY, scrnX+ZOOM_LOC_WIDTH-1, scrnY+ZOOM_LOC_HEIGHT-1, 0);
1163 }
1164 else
1165 {
1166 unsigned char v = thisRowLoc->visibility();
1167 if( v < MAX_VISIT_LEVEL-7)
1168 {
1169 // more visible draw 1/4 tone
1170 vga_back.pixelize_32x32(scrnX+1, scrnY, 0);
1171 vga_back.pixelize_32x32(scrnX, scrnY+1, 0);
1172 }
1173 // for visibility >= MAX_VISIT_LEVEL, draw nothing
1174 }
1175 }
1176 }
1177 }
1178 else
1179 {
1180 // use slow method
1181 scrnY = ZOOM_Y1;
1182 for( y = topLoc; y <= bottomLoc; ++y, scrnY += ZOOM_LOC_HEIGHT)
1183 {
1184 thisRowLoc = get_loc(leftLoc, y);
1185 northRowLoc = y > 0 ? get_loc(leftLoc, y-1) : thisRowLoc;
1186 southRowLoc = y+1 < max_y_loc ? get_loc(leftLoc, y+1): thisRowLoc;
1187
1188 // load north bit into bit0, north west bit into bit 1
1189 // [2] = west, [1] = this, [0] = east
1190 unsigned char northRow[3];
1191 unsigned char thisRow[3];
1192 unsigned char southRow[3];
1193 northRow[0] = northRowLoc->visibility();
1194 thisRow[0] = thisRowLoc->visibility();
1195 southRow[0] = southRowLoc->visibility();
1196
1197 if( leftLoc > 0)
1198 {
1199 northRow[1] = (northRowLoc-1)->visibility();
1200 thisRow[1] = (thisRowLoc-1)->visibility();
1201 southRow[1] = (southRowLoc-1)->visibility();
1202 }
1203 else
1204 {
1205 // copy [0] to [1]
1206 northRow[1] = northRow[0];
1207 thisRow[1] = thisRow[0];
1208 southRow[1] = southRow[0];
1209 }
1210
1211 scrnX = ZOOM_X1;
1212 for( x = leftLoc; x <= rightLoc; ++x, scrnX += ZOOM_LOC_WIDTH )
1213 {
1214 // shift to west
1215 northRow[2] = northRow[1]; northRow[1] = northRow[0];
1216 thisRow[2] = thisRow[1]; thisRow[1] = thisRow[0];
1217 southRow[2] = southRow[1]; southRow[1] = southRow[0];
1218
1219 // shift in east squares of each row
1220 if( x+1 < max_x_loc)
1221 {
1222 northRow[0] = (++northRowLoc)->visibility();
1223 thisRow[0] = (++thisRowLoc)->visibility();
1224 southRow[0] = (++southRowLoc)->visibility();
1225 }
1226 // if on the east of the map, simply replicate the eastest square
1227
1228 // ---------- Draw mask to vgabuf --------//
1229 unsigned char midNorthRow[3];
1230 unsigned char midThisRow[3];
1231 unsigned char midSouthRow[3];
1232 midThisRow[2] = MIN( thisRow[2], thisRow[1]);
1233 midThisRow[0] = MIN( thisRow[0], thisRow[1]);
1234 midNorthRow[2] = MIN( MIN(northRow[2], northRow[1]), midThisRow[2] );
1235 midNorthRow[1] = MIN( northRow[1], thisRow[1]);
1236 midNorthRow[0] = MIN( MIN(northRow[0], northRow[1]), midThisRow[0] );
1237 midSouthRow[2] = MIN( MIN(southRow[2], southRow[1]), midThisRow[2] );
1238 midSouthRow[1] = MIN( southRow[1], thisRow[1]);
1239 midSouthRow[0] = MIN( MIN(southRow[0], southRow[1]), midThisRow[0] );
1240 unsigned char midMean = ((int) thisRow[0] + thisRow[2] +
1241 northRow[0] + northRow[1] + northRow[2] +
1242 southRow[0] + southRow[1] + southRow[2] ) /8;
1243 midThisRow[1] = MIN(thisRow[1], midMean );
1244
1245 vga_back.fog_remap(scrnX, scrnY, (char **)explored_mask.brightness_table->get_table_array(),
1246 midNorthRow, midThisRow, midSouthRow);
1247 }
1248 }
1249 }
1250 }
1251 //---------- End of function ZoomMatrix::blacken_fog_of_war -----------//
1252
1253
1254 //--------- Begin of function ZoomMatrix::draw_objects ---------//
1255 //
1256 // Draw the following types of objects on the zoom map in a sorted order.
1257 //
1258 // 1. Firms
1259 // 2. Town sections
1260 // 3. Sprites
1261 //
draw_objects()1262 void ZoomMatrix::draw_objects()
1263 {
1264 //----- get the location of the zoom area ------//
1265
1266 const int DRAW_OUTSIDE = 3;
1267
1268 int zoomXLoc1 = world.zoom_matrix->top_x_loc - DRAW_OUTSIDE;
1269 int zoomYLoc1 = world.zoom_matrix->top_y_loc - DRAW_OUTSIDE;
1270 int zoomXLoc2 = world.zoom_matrix->top_x_loc + world.zoom_matrix->disp_x_loc - 1 + DRAW_OUTSIDE;
1271 int zoomYLoc2 = world.zoom_matrix->top_y_loc + world.zoom_matrix->disp_y_loc - 1 + DRAW_OUTSIDE;
1272
1273 if( zoomXLoc1 < 0)
1274 zoomXLoc1 = 0;
1275 if( zoomYLoc1 < 0)
1276 zoomYLoc1 = 0;
1277 if( zoomXLoc2 >= max_x_loc)
1278 zoomXLoc2 = max_x_loc-1;
1279 if( zoomYLoc2 >= max_y_loc)
1280 zoomYLoc2 = max_y_loc-1;
1281
1282 //---- add the objects on the zoom area to land_disp_sort_array in a sorted display order ---//
1283
1284 int xLoc, yLoc;
1285 Location* locPtr;
1286 DisplaySort displaySort;
1287 Unit* unitPtr;
1288 Firm* firmPtr;
1289 Town* townPtr;
1290 PlantBitmap* plantBitmap;
1291 int innerY, drawY;
1292 int dispFire = 0;
1293 // ####### begin Gilbert 31/7 ########//
1294 char pMobileType; // pointing mobileType
1295 Location* pLoc = power.test_detect(mouse.cur_x, mouse.cur_y, &pMobileType);
1296 // ####### end Gilbert 31/7 ########//
1297
1298 for( yLoc=zoomYLoc1 ; yLoc<=zoomYLoc2 ; yLoc++ )
1299 {
1300 locPtr = world.get_loc(zoomXLoc1,yLoc);
1301
1302 for( xLoc=zoomXLoc1 ; xLoc<=zoomXLoc2 ; xLoc++, locPtr++ )
1303 {
1304 //------- if there is an unit in the air --------//
1305
1306 if( locPtr->has_unit(UNIT_AIR) )
1307 {
1308 memset(&displaySort, 0, sizeof(displaySort));
1309 unitPtr = unit_array[locPtr->air_cargo_recno];
1310
1311 unitPtr->update_abs_pos(); // update its absolute position
1312
1313 displaySort.object_type = OBJECT_UNIT;
1314 displaySort.object_recno = locPtr->air_cargo_recno;
1315 displaySort.object_y2 = unitPtr->abs_y2;
1316
1317 if(pLoc == locPtr && pMobileType == UNIT_AIR)
1318 {
1319 displaySort.object_type = OBJECT_POINTED_UNIT;
1320 // BUGHERE : this part may fails if sprite size > 1x1
1321 }
1322
1323 if( !unitPtr->is_shealth() )
1324 {
1325 if( unitPtr->sprite_info->loc_width > 1 )
1326 {
1327 if( xLoc==MAX( unitPtr->next_x_loc(), zoomXLoc1 ) &&
1328 yLoc==MAX( unitPtr->next_y_loc(), zoomYLoc1 ) )
1329 {
1330 air_disp_sort_array.linkin(&displaySort);
1331 }
1332 }
1333 else
1334 {
1335 air_disp_sort_array.linkin(&displaySort);
1336 }
1337 }
1338 }
1339
1340 //------- if there is an unit on the land or sea -------//
1341
1342 if( locPtr->has_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA) )
1343 {
1344 memset(&displaySort, 0, sizeof(displaySort));
1345 unitPtr = unit_array[locPtr->cargo_recno];
1346
1347 unitPtr->update_abs_pos(); // update its absolute position
1348
1349 displaySort.object_type = OBJECT_UNIT;
1350 displaySort.object_recno = locPtr->cargo_recno;
1351 displaySort.object_y2 = unitPtr->abs_y2;
1352
1353 if( pLoc == locPtr && (pMobileType == UNIT_LAND || pMobileType == UNIT_SEA))
1354 {
1355 displaySort.object_type = OBJECT_POINTED_UNIT;
1356 // BUGHERE : this part may fails if sprite size > 1x1
1357 }
1358
1359 if( !unitPtr->is_shealth() )
1360 {
1361 if( unitPtr->sprite_info->loc_width > 1 )
1362 {
1363 if( xLoc==MAX( unitPtr->next_x_loc(), zoomXLoc1 ) &&
1364 yLoc==MAX( unitPtr->next_y_loc(), zoomYLoc1 ) )
1365 {
1366 land_disp_sort_array.linkin(&displaySort);
1367 }
1368 }
1369 else
1370 {
1371 land_disp_sort_array.linkin(&displaySort);
1372 }
1373 }
1374 }
1375
1376 //--------- if there is a firm on the location --------//
1377
1378 else if( locPtr->is_firm() )
1379 {
1380 memset(&displaySort, 0, sizeof(displaySort));
1381 displaySort.object_type = OBJECT_FIRM;
1382 displaySort.object_recno = locPtr->firm_recno();
1383
1384 firmPtr = firm_array[locPtr->firm_recno()];
1385
1386 displaySort.object_y2 = firmPtr->abs_y2;
1387
1388 if( xLoc==MAX( firmPtr->loc_x1, zoomXLoc1 ) &&
1389 yLoc==MAX( firmPtr->loc_y1, zoomYLoc1 ) )
1390 {
1391 land_bottom_disp_sort_array.linkin(&displaySort);
1392 land_disp_sort_array.linkin(&displaySort);
1393 }
1394 }
1395
1396 //------ if there is a town section on the location -----//
1397
1398 else if( locPtr->is_town() )
1399 {
1400 memset(&displaySort, 0, sizeof(displaySort));
1401 displaySort.object_type = OBJECT_TOWN;
1402 displaySort.object_recno = locPtr->town_recno();
1403
1404 townPtr = town_array[locPtr->town_recno()];
1405
1406 displaySort.object_y2 = townPtr->abs_y2;
1407
1408 if( xLoc==MAX( townPtr->loc_x1, zoomXLoc1 ) &&
1409 yLoc==MAX( townPtr->loc_y1, zoomYLoc1 ) )
1410 {
1411 land_bottom_disp_sort_array.linkin(&displaySort);
1412 land_disp_sort_array.linkin(&displaySort);
1413 }
1414 }
1415
1416 //------ if there is a plant on the location -----//
1417
1418 else if( locPtr->is_plant() )
1419 {
1420 memset(&displaySort, 0, sizeof(displaySort));
1421 displaySort.object_type = OBJECT_PLANT;
1422 displaySort.object_recno = locPtr->plant_id();
1423
1424 plantBitmap = plant_res.get_bitmap(locPtr->plant_id());
1425
1426 innerY = locPtr->plant_inner_y();
1427 drawY = yLoc*ZOOM_LOC_HEIGHT + innerY-ZOOM_LOC_HEIGHT/2 + plantBitmap->offset_y + plantBitmap->bitmap_height - 1;
1428
1429 displaySort.object_y2 = drawY;
1430 displaySort.x_loc = xLoc;
1431 displaySort.y_loc = yLoc;
1432
1433 land_disp_sort_array.linkin(&displaySort);
1434 }
1435
1436 //------ if there is a wall on the location -------//
1437
1438 else if( locPtr->is_wall() )
1439 {
1440 memset(&displaySort, 0, sizeof(displaySort));
1441 WallInfo *wallInfo = wall_res[locPtr->wall_id()];
1442 displaySort.object_type = OBJECT_WALL;
1443
1444 // high byte of object_recno stores nation_recno
1445 // low byte of object_recno stores wall_id
1446 displaySort.object_recno = wallInfo->draw_wall_id;
1447 if( locPtr->power_nation_recno > 0)
1448 {
1449 displaySort.object_recno += locPtr->power_nation_recno << 8;
1450 }
1451 if( ! wallInfo->is_gate())
1452 {
1453 // -------- non-gate square
1454 displaySort.object_y2 = yLoc* ZOOM_LOC_HEIGHT +ZOOM_LOC_HEIGHT-1;
1455 displaySort.x_loc = xLoc * ZOOM_LOC_WIDTH;
1456 displaySort.y_loc = yLoc * ZOOM_LOC_HEIGHT;
1457 land_disp_sort_array.linkin(&displaySort);
1458 }
1459 else
1460 {
1461 // -------- gate square ---------//
1462 displaySort.object_y2 = yLoc * ZOOM_LOC_HEIGHT + wallInfo->offset_y +
1463 wallInfo->bitmap_height() -1;
1464 displaySort.x_loc = xLoc + wallInfo->loc_off_x;
1465 displaySort.y_loc = yLoc + wallInfo->loc_off_y;
1466 if( xLoc == MAX( displaySort.x_loc, zoomXLoc1) &&
1467 yLoc == MAX( displaySort.y_loc, zoomYLoc1) )
1468 {
1469 displaySort.x_loc = xLoc * ZOOM_LOC_WIDTH + wallInfo->offset_x;
1470 displaySort.y_loc = yLoc * ZOOM_LOC_HEIGHT + wallInfo->offset_y;
1471 land_disp_sort_array.linkin(&displaySort);
1472 }
1473 }
1474 }
1475 else if(locPtr->has_hill() && hill_res[locPtr->hill_id1()]->layer & 2 )
1476 {
1477 memset(&displaySort, 0, sizeof(displaySort));
1478 displaySort.object_type = OBJECT_HILL;
1479 displaySort.object_recno = locPtr->hill_id1();
1480 displaySort.object_y2 = (yLoc+1)*ZOOM_LOC_HEIGHT-1;
1481 displaySort.x_loc = xLoc;
1482 displaySort.y_loc = yLoc;
1483 land_disp_sort_array.linkin(&displaySort);
1484 }
1485 else if(locPtr->is_rock())
1486 {
1487 memset(&displaySort, 0, sizeof(displaySort));
1488 displaySort.object_type = OBJECT_ROCK;
1489 Rock *rockPtr = rock_array[displaySort.object_recno = locPtr->rock_array_recno()];
1490 displaySort.object_y2 = ZOOM_LOC_HEIGHT * (rockPtr->loc_y
1491 + rock_res.get_rock_info(rockPtr->rock_recno)->loc_height) -1;
1492
1493 if( xLoc==MAX( rockPtr->loc_x, zoomXLoc1 ) &&
1494 yLoc==MAX( rockPtr->loc_y, zoomYLoc1 ) )
1495 {
1496 land_disp_sort_array.linkin(&displaySort);
1497 }
1498 }
1499
1500 #ifdef DEBUG2
1501 if(debug_sim_game_type!=2 && locPtr->fire_str()>0)
1502 #else
1503 if( locPtr->fire_str() > 0 )
1504 #endif
1505 {
1506 memset(&displaySort, 0, sizeof(displaySort));
1507 displaySort.object_type = OBJECT_FIRE;
1508 displaySort.object_recno = locPtr->fire_str();
1509 displaySort.object_y2 = (yLoc+1)*ZOOM_LOC_HEIGHT -
1510 ((((xLoc+13) * (yLoc+17)) % 16) & ~1);
1511
1512 displaySort.x_loc = xLoc;
1513 displaySort.y_loc = yLoc;
1514
1515 land_disp_sort_array.linkin(&displaySort);
1516 land_top_disp_sort_array.linkin(&displaySort);
1517 dispFire++;
1518 }
1519
1520 }
1521 }
1522
1523 //------ add bullet sprites to the display array -------//
1524
1525 Bullet* bulletPtr;
1526
1527 int i;
1528 for( i=bullet_array.size() ; i>0 ; i-- )
1529 {
1530 if( bullet_array.is_deleted(i) )
1531 continue;
1532
1533 bulletPtr = bullet_array[i];
1534
1535 // ######### begin Gilbert 20/6 #########//
1536 if( bulletPtr->is_shealth() ||
1537 bulletPtr->cur_x_loc() < zoomXLoc1 || bulletPtr->cur_x_loc() > zoomXLoc2 ||
1538 bulletPtr->cur_y_loc() < zoomYLoc1 || bulletPtr->cur_y_loc() > zoomYLoc2 )
1539 continue;
1540 // ######### end Gilbert 20/6 #########//
1541
1542 bulletPtr->update_abs_pos(); // update its absolute position
1543
1544 displaySort.object_type = OBJECT_BULLET;
1545 displaySort.object_recno = i;
1546 displaySort.object_y2 = bulletPtr->abs_y2;
1547
1548 switch( bulletPtr->display_layer() )
1549 {
1550 case AIR_DISP_LAYER_MASK:
1551 air_disp_sort_array.linkin(&displaySort);
1552 break;
1553 case LAND_BOTTOM_DISP_LAYER_MASK:
1554 land_bottom_disp_sort_array.linkin(&displaySort);
1555 break;
1556 case LAND_TOP_DISP_LAYER_MASK:
1557 land_top_disp_sort_array.linkin(&displaySort);
1558 break;
1559 case 0:
1560 case LAND_DISP_LAYER_MASK:
1561 land_disp_sort_array.linkin(&displaySort);
1562 break;
1563 default:
1564 err_here();
1565 }
1566 }
1567
1568 // --------- draw tornado --------//
1569 Tornado *tornadoPtr;
1570 for( i=tornado_array.size(); i > 0; i--)
1571 {
1572 if( tornado_array.is_deleted(i) )
1573 continue;
1574 tornadoPtr = tornado_array[i];
1575 // ######### begin Gilbert 28/5 #########//
1576 // if( tornadoPtr->is_shealth() )
1577 if( // tornadoPtr->is_shealth() ||
1578 tornadoPtr->cur_x_loc() < zoomXLoc1 || tornadoPtr->cur_x_loc() > zoomXLoc2 ||
1579 tornadoPtr->cur_y_loc() < zoomYLoc1 || tornadoPtr->cur_y_loc() > zoomYLoc2 )
1580 continue;
1581 // ######### end Gilbert 28/5 #########//
1582
1583 tornadoPtr->update_abs_pos();
1584
1585 displaySort.object_type = OBJECT_TORNADO;
1586 displaySort.object_recno = i;
1587 displaySort.object_y2 = tornadoPtr->abs_y2;
1588 air_disp_sort_array.linkin(&displaySort);
1589 }
1590
1591 for( i=effect_array.size(); i > 0; i--)
1592 {
1593 if( effect_array.is_deleted(i) )
1594 continue;
1595 Effect *effectPtr = (Effect *)effect_array[i];
1596 // ######### begin Gilbert 28/5 #########//
1597 if( effectPtr->is_shealth() ||
1598 effectPtr->cur_x_loc() < zoomXLoc1 || effectPtr->cur_x_loc() > zoomXLoc2 ||
1599 effectPtr->cur_y_loc() < zoomYLoc1 || effectPtr->cur_y_loc() > zoomYLoc2 )
1600 continue;
1601 // ######### end Gilbert 28/5 #########//
1602 effectPtr->update_abs_pos();
1603
1604 displaySort.object_type = OBJECT_EFFECT;
1605 displaySort.object_recno = i;
1606 displaySort.object_y2 = effectPtr->abs_y2;
1607
1608 switch( effectPtr->layer )
1609 {
1610 case AIR_DISP_LAYER_MASK:
1611 air_disp_sort_array.linkin(&displaySort);
1612 break;
1613 case LAND_BOTTOM_DISP_LAYER_MASK:
1614 land_bottom_disp_sort_array.linkin(&displaySort);
1615 break;
1616 case LAND_TOP_DISP_LAYER_MASK:
1617 land_top_disp_sort_array.linkin(&displaySort);
1618 break;
1619 case 0:
1620 case LAND_DISP_LAYER_MASK:
1621 land_disp_sort_array.linkin(&displaySort);
1622 break;
1623 default:
1624 err_here();
1625 }
1626 }
1627
1628 // ###### begin Gilbert 2/10 #######//
1629 for( i=firm_die_array.size(); i > 0; i--)
1630 {
1631 if( firm_die_array.is_deleted(i) )
1632 continue;
1633
1634 FirmDie *firmDiePtr = (FirmDie *)firm_die_array[i];
1635
1636 if( firmDiePtr->loc_x2 < zoomXLoc1 || firmDiePtr->loc_x1 > zoomXLoc2 ||
1637 firmDiePtr->loc_y2 < zoomYLoc1 || firmDiePtr->loc_y1 > zoomYLoc2 )
1638 continue;
1639
1640 //--------- if there is a dying firm on the location --------//
1641
1642 memset(&displaySort, 0, sizeof(displaySort));
1643 displaySort.object_type = OBJECT_FIRM_DIE;
1644 displaySort.object_recno = i;
1645
1646 displaySort.object_y2 = firmDiePtr->loc_y2 * ZOOM_LOC_HEIGHT;
1647
1648 land_bottom_disp_sort_array.linkin(&displaySort);
1649 land_disp_sort_array.linkin(&displaySort);
1650 }
1651 // ###### end Gilbert 2/10 #######//
1652
1653
1654 //---------- quicksort the array -----------//
1655
1656 land_disp_sort_array.quick_sort( sort_display_function );
1657 air_disp_sort_array.quick_sort( sort_display_function );
1658 land_top_disp_sort_array.quick_sort( sort_display_function );
1659 land_bottom_disp_sort_array.quick_sort( sort_display_function );
1660
1661 // ##### begin Gilbert 9/10 ######//
1662 //------------ draw unit path and objects ---------------//
1663
1664 draw_objects_now(&land_bottom_disp_sort_array, LAND_BOTTOM_DISP_LAYER_MASK);
1665 draw_unit_path_on_zoom_map(LAND_DISP_LAYER_MASK);
1666 draw_objects_now(&land_disp_sort_array,LAND_DISP_LAYER_MASK);
1667 draw_objects_now(&land_top_disp_sort_array,LAND_TOP_DISP_LAYER_MASK);
1668
1669 draw_unit_path_on_zoom_map(AIR_DISP_LAYER_MASK);
1670 draw_unit_way_point_on_zoom_map();
1671 draw_objects_now(&air_disp_sort_array);
1672 // ##### end Gilbert 9/10 ######//
1673
1674
1675 //----------- clean up the array ----------//
1676
1677 land_disp_sort_array.zap(0); // 0-don't resize the array, keep its current size
1678 air_disp_sort_array.zap(0); // 0-don't resize the array, keep its current size
1679 land_top_disp_sort_array.zap(0);
1680 land_bottom_disp_sort_array.zap(0);
1681
1682 //----------- fire sound ----------//
1683 if(dispFire > 0)
1684 {
1685 int relVolume = 80 + dispFire/2;
1686 if( relVolume > 100)
1687 relVolume = 100;
1688 if( fire_channel_id == 0)
1689 {
1690 last_fire_vol = relVolume;
1691 RelVolume r(relVolume,0);
1692 fire_channel_id = audio.play_loop_wav( DIR_SOUND"FIRE.WAV",8447 *2, DsVolume(r));
1693 }
1694 else if( last_fire_vol - relVolume > 2 || last_fire_vol - relVolume < 2)
1695 {
1696 last_fire_vol = relVolume;
1697 RelVolume r(relVolume,0);
1698 audio.volume_loop_wav(fire_channel_id, DsVolume(r));
1699 }
1700 }
1701 else
1702 {
1703 if( fire_channel_id != 0)
1704 {
1705 audio.stop_loop_wav(fire_channel_id);
1706 fire_channel_id = 0;
1707 last_fire_vol = 0;
1708 }
1709 }
1710 }
1711 //----------- End of function ZoomMatrix::draw_objects -----------//
1712
1713
1714 //---------- Begin of function ZoomMatrix::draw_objects_now -----------//
1715 //
draw_objects_now(DynArray * unitArray,int displayLayer)1716 void ZoomMatrix::draw_objects_now(DynArray* unitArray, int displayLayer)
1717 {
1718 //------------ display objects ------------//
1719
1720 DisplaySort *displaySortPtr;
1721 Firm *firmPtr;
1722 int i, dispCount = unitArray->size();
1723 char firstFire[FLAME_GROW_STEP];
1724 memset( firstFire, 0, sizeof(firstFire));
1725 int riseFirePara = 0;
1726 int needFlushFire = weather.rain_scale() + weather.snow_scale();
1727 double hWindSpeed = weather.wind_speed()*sin(weather.wind_direct_rad());
1728 if( hWindSpeed >= 20.0)
1729 riseFirePara = 1;
1730 else if( hWindSpeed > -20.0)
1731 riseFirePara = 0;
1732 else
1733 riseFirePara = -1;
1734
1735 if( init_fire <= flame[FLAME_GROW_STEP-1].map_height)
1736 {
1737 for( int f = FLAME_GROW_STEP-1 ; f >= 0; --f)
1738 {
1739 if( init_fire <= flame[f].map_height)
1740 {
1741 flame[f].rise(riseFirePara);
1742 }
1743 else
1744 {
1745 break;
1746 }
1747 }
1748 init_fire++;
1749 }
1750
1751 int dispPower = (world.map_matrix->map_mode == MAP_MODE_POWER &&
1752 world.map_matrix->power_mode == 1) ||
1753 power.command_id == COMMAND_BUILD_FIRM ||
1754 power.command_id == COMMAND_SETTLE ||
1755 power.command_id == COMMAND_BUILD_WALL;
1756
1757 for( i=1 ; i<=dispCount ; i++ )
1758 {
1759 if( i%10==1 )
1760 sys.yield();
1761
1762 displaySortPtr = (DisplaySort*) unitArray->get(i);
1763
1764 switch(displaySortPtr->object_type)
1765 {
1766 case OBJECT_UNIT:
1767 unit_array[displaySortPtr->object_recno]->draw();
1768 break;
1769
1770 case OBJECT_POINTED_UNIT:
1771 unit_array[displaySortPtr->object_recno]->draw_outlined();
1772 break;
1773
1774 case OBJECT_BULLET:
1775 bullet_array[displaySortPtr->object_recno]->draw();
1776 break;
1777
1778 case OBJECT_FIRM:
1779 firmPtr = firm_array[displaySortPtr->object_recno];
1780 firmPtr->draw(displayLayer);
1781 break;
1782
1783 case OBJECT_TOWN:
1784 town_array[displaySortPtr->object_recno]->draw(displayLayer);
1785 break;
1786
1787 case OBJECT_PLANT:
1788 plant_res.get_bitmap(displaySortPtr->object_recno)
1789 ->draw(displaySortPtr->x_loc, displaySortPtr->y_loc);
1790 break;
1791
1792 case OBJECT_ROCK:
1793 // object_recno is rockArrayRecno
1794 rock_array[displaySortPtr->object_recno]->draw();
1795 break;
1796
1797 case OBJECT_FIRE:
1798 {
1799 int f;
1800 // when displayLayer = 0, no fire is assumed to be drawn
1801 // pass fireDisplayerLayer as 1 to this function
1802 err_when(!displayLayer);
1803
1804 // ------- decide bitmap to draw ----
1805 // display flame[f], where f = (fire_str()-1) /25
1806 f = Flame::grade( displaySortPtr->object_recno );
1807 err_when(f >= FLAME_GROW_STEP);
1808 if( !firstFire[f])
1809 {
1810 firstFire[f] = 1;
1811 if( displayLayer == 1)
1812 {
1813 if( needFlushFire )
1814 flame[f].flush_point();
1815 flame[f].rise(riseFirePara);
1816 flame[f].gen_bitmap(0xe3); // 0xb4
1817 flame[f].mask_bottom();
1818 }
1819 else
1820 {
1821 flame[f].mask_transparent();
1822 }
1823 }
1824
1825 int x1 = displaySortPtr->x_loc * ZOOM_LOC_WIDTH + Flame::offset_x(f) - World::view_top_x;
1826 int y1 = displaySortPtr->y_loc * ZOOM_LOC_HEIGHT + Flame::offset_y(f) - World::view_top_y;
1827
1828 // ------- shift 'randomly' but even number---------
1829 x1 += (((displaySortPtr->x_loc+11) * (displaySortPtr->y_loc+13)) % 16) & ~1;
1830 x1 -= 6;
1831 y1 -= (((displaySortPtr->x_loc+13) * (displaySortPtr->y_loc+17)) % 16) & ~1;
1832
1833 int x2 = x1 + Flame::default_width(f) -1;
1834 int y2 = y1 + Flame::default_height(f) -1;
1835
1836 if( x2 >= 0 && x1 < ZOOM_WIDTH && y2 >= 0 && y1 < ZOOM_HEIGHT )
1837 {
1838 if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
1839 {
1840 vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, (char *)flame[f].bitmap,
1841 MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1 );
1842 }
1843 else
1844 {
1845 vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, (char *)flame[f].bitmap );
1846 }
1847 }
1848 }
1849 break;
1850
1851 case OBJECT_WALL:
1852 {
1853 int nationRecno = displaySortPtr->object_recno >> 8;
1854 char *remapTable = game.get_color_remap_table(nationRecno, 0);
1855 wall_res[displaySortPtr->object_recno & 0xff]->draw_at(
1856 displaySortPtr->x_loc, displaySortPtr->y_loc, remapTable);
1857 }
1858 break;
1859 case OBJECT_TORNADO:
1860 tornado_array[displaySortPtr->object_recno]->draw();
1861 break;
1862
1863 case OBJECT_HILL:
1864 {
1865 short xLoc = displaySortPtr->x_loc;
1866 short yLoc = displaySortPtr->y_loc;
1867 hill_res[displaySortPtr->object_recno]->draw(xLoc, yLoc, 2);
1868
1869 // ------ draw power, because hill covers the power colour drawn ------//
1870 int nationRecno = get_loc(xLoc, yLoc)->power_nation_recno;
1871 if( dispPower && nationRecno > 0)
1872 {
1873 int x1 = xLoc*ZOOM_LOC_WIDTH - World::view_top_x;
1874 int y1 = yLoc*ZOOM_LOC_HEIGHT - World::view_top_y;
1875 if( x1 >= 0 && y1 >= 0 && x1 < ZOOM_WIDTH - (ZOOM_LOC_WIDTH-1) && y1 < ZOOM_HEIGHT - (ZOOM_LOC_HEIGHT-1))
1876 {
1877 vga_back.pixelize_32x32( x1 + ZOOM_X1, y1 + ZOOM_Y1,
1878 nation_array.nation_power_color_array[nationRecno] );
1879 }
1880 }
1881 }
1882 break;
1883
1884 // #### begin Gilbert 4/10 #######//
1885 case OBJECT_EFFECT:
1886 effect_array[displaySortPtr->object_recno]->draw();
1887 break;
1888
1889 case OBJECT_FIRM_DIE:
1890 firm_die_array[displaySortPtr->object_recno]->draw(displayLayer);
1891 break;
1892 // #### end Gilbert 4/10 #######//
1893 }
1894 }
1895 }
1896 //----------- End of function ZoomMatrix::draw_objects_now ------------//
1897
1898
1899 //---------- Begin of function ZoomMatrix::scroll -----------//
1900 //
1901 // <int> xScroll - horizontal scroll step (negative:left, positive:right)
1902 // <int> yScroll - vertical scroll step (negative:left, positive:right)
1903 //
scroll(int xScroll,int yScroll)1904 void ZoomMatrix::scroll(int xScroll, int yScroll)
1905 {
1906 Matrix::scroll(xScroll,yScroll);
1907
1908 world.map_matrix->cur_x_loc = top_x_loc;
1909 world.map_matrix->cur_y_loc = top_y_loc;
1910 }
1911 //----------- End of function ZoomMatrix::scroll ------------//
1912
1913
1914 //------ Begin of function sort_display_function ------//
1915 //
sort_display_function(const void * a,const void * b)1916 static int sort_display_function( const void *a, const void *b )
1917 {
1918 return ((DisplaySort*)a)->object_y2 - ((DisplaySort*)b)->object_y2;
1919 }
1920 //------- End of function sort_display_function ------//
1921
1922
1923 //------ Begin of function ZoomMatrix::put_bitmap_clip ---------//
1924 //
1925 // Put a bitmap on the surface buffer
1926 //
1927 // <int> x, y - the location of the bitmap, in the current screen coordination
1928 // <char*> bitmapPtr - bitmap ptr
1929 // [int] compressedFlag - whether the bitmap is compressed or not
1930 // (default: 0)
1931 //
put_bitmap_clip(int x,int y,char * bitmapPtr,int compressedFlag)1932 void ZoomMatrix::put_bitmap_clip(int x, int y, char* bitmapPtr, int compressedFlag)
1933 {
1934 int x2 = x + *((short*)bitmapPtr) - 1;
1935 int y2 = y + *(((short*)bitmapPtr)+1) - 1;
1936
1937 if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 )
1938 return;
1939
1940 //---- only portion of the sprite is inside the view area ------//
1941
1942 if( x < ZOOM_X1 || x2 > ZOOM_X2 || y < ZOOM_Y1 || y2 > ZOOM_Y2 )
1943 {
1944 if( compressedFlag )
1945 {
1946 vga_back.put_bitmap_area_trans_decompress( x, y, bitmapPtr,
1947 MAX(ZOOM_X1,x)-x, MAX(ZOOM_Y1,y)-y, MIN(ZOOM_X2,x2)-x, MIN(ZOOM_Y2,y2)-y );
1948 }
1949 else
1950 {
1951 vga_back.put_bitmap_area_trans( x, y, bitmapPtr,
1952 MAX(ZOOM_X1,x)-x, MAX(ZOOM_Y1,y)-y, MIN(ZOOM_X2,x2)-x, MIN(ZOOM_Y2,y2)-y );
1953 }
1954 }
1955
1956 //---- the whole sprite is inside the view area ------//
1957
1958 else
1959 {
1960 if( compressedFlag )
1961 vga_back.put_bitmap_trans_decompress( x, y, bitmapPtr );
1962 else
1963 vga_back.put_bitmap_trans( x, y, bitmapPtr );
1964 }
1965 }
1966 //--------- End of function ZoomMatrix::put_bitmap_clip ---------//
1967
1968
1969 //------ Begin of function ZoomMatrix::detect_bitmap_clip ---------//
1970 //
1971 // Detect clicking on the bitmap.
1972 //
1973 // return: <int> 0 - not detected
1974 // 1 - left clicked
1975 // 2 - right clicked
1976 //
detect_bitmap_clip(int x,int y,char * bitmapPtr)1977 int ZoomMatrix::detect_bitmap_clip(int x, int y, char* bitmapPtr)
1978 {
1979 int x2 = x + *((short*)bitmapPtr) - 1;
1980 int y2 = y + *(((short*)bitmapPtr)+1) - 1;
1981
1982 if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 )
1983 return 0;
1984
1985 //---- only portion of the sprite is inside the view area ------//
1986
1987 // return mouse.single_click( MAX(ZOOM_X1,x), MAX(ZOOM_Y1,y), MIN(ZOOM_X2,x2), MIN(ZOOM_Y2,y2), 2 );
1988 return mouse.any_click( MAX(ZOOM_X1,x), MAX(ZOOM_Y1,y), MIN(ZOOM_X2,x2), MIN(ZOOM_Y2,y2), 0 ) ? 1 :
1989 mouse.any_click( MAX(ZOOM_X1,x), MAX(ZOOM_Y1,y), MIN(ZOOM_X2,x2), MIN(ZOOM_Y2,y2), 1 ) ? 2 : 0;
1990 }
1991 //--------- End of function ZoomMatrix::detect_bitmap_clip ---------//
1992
1993
1994 //------ Begin of function ZoomMatrix::is_bitmap_clip ---------//
1995 //
1996 // Returns true if the bitmap is (partially) inside the zoom region, or false otherwise
1997 //
1998 // return: <bool> false - completely outside zoom
1999 // true - (partially) inside zoom
2000 //
is_bitmap_clip(int x,int y,char * bitmapPtr)2001 bool ZoomMatrix::is_bitmap_clip(int x, int y, char* bitmapPtr)
2002 {
2003 int x2 = x + *((short*)bitmapPtr) - 1;
2004 int y2 = y + *(((short*)bitmapPtr)+1) - 1;
2005
2006 if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 )
2007 return 0;
2008
2009 return 1;
2010 }
2011 //--------- End of function ZoomMatrix::is_bitmap_clip ---------//
2012
2013
2014 //------ Begin of function ZoomMatrix::put_bitmap_remap_clip ---------//
2015 //
2016 // Put a bitmap on the surface buffer
2017 //
2018 // <int> x, y - the location of the bitmap
2019 // <char*> bitmapPtr - bitmap ptr
2020 // [char*] colorRemapTable - color remap table
2021 // [int] compressedFlag - whether the bitmap is compressed or not
2022 // (default: 0)
2023 //
put_bitmap_remap_clip(int x,int y,char * bitmapPtr,char * colorRemapTable,int compressedFlag)2024 void ZoomMatrix::put_bitmap_remap_clip(int x, int y, char* bitmapPtr, char* colorRemapTable, int compressedFlag)
2025 {
2026 int x2 = x + *((short*)bitmapPtr) - 1;
2027 int y2 = y + *(((short*)bitmapPtr)+1) - 1;
2028
2029 if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 )
2030 return;
2031
2032 //---- only portion of the sprite is inside the view arec ------//
2033
2034 if( x < ZOOM_X1 || x2 > ZOOM_X2 || y < ZOOM_Y1 || y2 > ZOOM_Y2 )
2035 {
2036 if( compressedFlag )
2037 {
2038 if( colorRemapTable )
2039 {
2040 vga_back.put_bitmap_area_trans_remap_decompress( x, y, bitmapPtr,
2041 MAX(ZOOM_X1,x)-x, MAX(ZOOM_Y1,y)-y, MIN(ZOOM_X2,x2)-x, MIN(ZOOM_Y2,y2)-y, colorRemapTable );
2042 }
2043 else
2044 {
2045 vga_back.put_bitmap_area_trans_decompress( x, y, bitmapPtr,
2046 MAX(ZOOM_X1,x)-x, MAX(ZOOM_Y1,y)-y, MIN(ZOOM_X2,x2)-x, MIN(ZOOM_Y2,y2)-y );
2047 }
2048 }
2049 else
2050 {
2051 if( colorRemapTable )
2052 {
2053 vga_back.put_bitmap_area_trans_remap( x, y, bitmapPtr,
2054 MAX(ZOOM_X1,x)-x, MAX(ZOOM_Y1,y)-y, MIN(ZOOM_X2,x2)-x, MIN(ZOOM_Y2,y2)-y, colorRemapTable );
2055 }
2056 else
2057 {
2058 vga_back.put_bitmap_area_trans( x, y, bitmapPtr,
2059 MAX(ZOOM_X1,x)-x, MAX(ZOOM_Y1,y)-y, MIN(ZOOM_X2,x2)-x, MIN(ZOOM_Y2,y2)-y );
2060 }
2061 }
2062 }
2063
2064 //---- the whole sprite is inside the view area ------//
2065
2066 else
2067 {
2068 if( compressedFlag )
2069 {
2070 if( colorRemapTable )
2071 vga_back.put_bitmap_trans_remap_decompress( x, y, bitmapPtr, colorRemapTable );
2072 else
2073 vga_back.put_bitmap_trans_decompress( x, y, bitmapPtr );
2074 }
2075 else
2076 {
2077 if( colorRemapTable )
2078 vga_back.put_bitmap_trans_remap( x, y, bitmapPtr, colorRemapTable );
2079 else
2080 vga_back.put_bitmap_trans( x, y, bitmapPtr );
2081 }
2082 }
2083 }
2084 //--------- End of function ZoomMatrix::put_bitmap_remap_clip ---------//
2085