OWORLD_Z.cpp 58 KB

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