/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OWORLD_Z.CPP //Description : Object ZoomMatrix #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //--------- Define static vars -----------// //static int init_rain = 0; // reset on new game and load game static Rain rain; //static int rain_channel_id = 0; // reset on new game and load game //static int wind_channel_id = 0; // reset on new game and load game //static int fire_channel_id = 0; // reset on new game and load game //static int last_fire_vol = 0; // reset on new game and load game //static int init_lightning = 0; // reset on new game, save on save game static YLightning lightning; //static int init_snow = 0; // reset on new game and load game static Snow snow; //static short last_brightness = 0; // reset on new game and load game //static int vibration = -1; // reset on new game, save on save game //static short lightning_x1, lightning_y1, lightning_x2, lightning_y2; // save on save game static int init_fire = -10; // reset on new game and load game //-------- Declare static functions ---------// static int sort_display_function( const void *a, const void *b ); //------- Define constant for object_type --------// enum { OBJECT_UNIT, OBJECT_POINTED_UNIT, OBJECT_BULLET, OBJECT_FIRM, OBJECT_TOWN, OBJECT_PLANT, OBJECT_FIRE, OBJECT_WALL, OBJECT_TORNADO, OBJECT_HILL, OBJECT_ROCK, OBJECT_EFFECT, // ###### begin Gilbert 2/10 #######// OBJECT_FIRM_DIE, // ###### end Gilbert 2/10 #######// }; enum { LAND_DISP_LAYER_MASK=1, LAND_TOP_DISP_LAYER_MASK=2, LAND_BOTTOM_DISP_LAYER_MASK=4, AIR_DISP_LAYER_MASK=8, }; //---------- Define struct DisplaySort ----------// struct DisplaySort { char object_type; short object_recno; short object_y2; short x_loc, y_loc; }; //------------ begin of static function draw_unit_path_on_zoom_map -----------// // ##### begin Gilbert 9/10 #######// static void draw_unit_path_on_zoom_map(int displayLayer) // ##### end Gilbert 9/10 #######// { // ###### begin Gilbert 29/8 ######// if( !(config.show_unit_path & 1) ) return; // ###### end Gilbert 29/8 ######// short nationRecno = nation_array.player_recno; Unit *unitPtr; int i, j, resultNodeCount, resultNodeRecno; short lineFromX, lineFromY, lineToX, lineToY; ResultNode *resultNode1, *resultNode2; for(i=unit_array.size(); i>0; --i) { if(unit_array.is_deleted(i)) continue; unitPtr = unit_array[i]; if(!unitPtr->is_visible()) continue; if(!unitPtr->selected_flag) continue; // ####### begin Gilbert 11/9 #######// if( !config.show_ai_info && nationRecno && !unitPtr->is_nation(nationRecno) ) continue; // ####### end Gilbert 11/9 #######// // ##### begin Gilbert 9/10 #######// if( unitPtr->mobile_type == UNIT_LAND || unitPtr->mobile_type == UNIT_SEA ) { if( !(displayLayer & LAND_DISP_LAYER_MASK) ) continue; } else if( unitPtr->mobile_type == UNIT_AIR ) { if( !(displayLayer & AIR_DISP_LAYER_MASK) ) continue; } else { err_here(); continue; } // ##### end Gilbert 9/10 #######// //--------------- draw unit's path ----------------// resultNodeRecno = unitPtr->result_node_recno; resultNodeCount = unitPtr->result_node_count; if(!resultNodeCount || resultNodeRecno>resultNodeCount) continue; //-----------------------------------------------------------// if(unitPtr->cur_x!=unitPtr->go_x || unitPtr->cur_y!=unitPtr->go_y) { lineFromX = unitPtr->go_x - world.zoom_matrix->top_x_loc*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2; lineFromY = unitPtr->go_y - world.zoom_matrix->top_y_loc*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2; lineToX = unitPtr->cur_x - world.zoom_matrix->top_x_loc*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2; lineToY = unitPtr->cur_y - world.zoom_matrix->top_y_loc*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2; anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY); } //-----------------------------------------------------------// err_when(resultNodeRecno<1); resultNode1 = unitPtr->result_node_array + resultNodeRecno - 1; resultNode2 = resultNode1 + 1; lineToX = (resultNode1->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2; lineToY = (resultNode1->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2; for(j=resultNodeRecno+1; j<=resultNodeCount; j++, resultNode1++, resultNode2++) { lineFromX = (resultNode2->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2; lineFromY = (resultNode2->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2; anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY); lineToX = lineFromX; lineToY = lineFromY; } } } //------------ end of static function draw_unit_path_on_zoom_map -----------// //------------ begin of static function draw_unit_way_point_on_zoom_map -----------// static void draw_unit_way_point_on_zoom_map() { short nationRecno = nation_array.player_recno; Unit *unitPtr; int i, j, resultNodeCount; short lineFromX, lineFromY, lineToX, lineToY; ResultNode *resultNode1, *resultNode2; // ##### begin Gilbert 12/11 #######// char *chPtr = image_icon.get_ptr("WAYPOINT"); short chOffsetX = - (*(short *)chPtr / 2); short chOffsetY = - (*(1+(short *)chPtr) / 2); // ##### end Gilbert 12/11 #######// for(i=unit_array.size(); i>0; --i) { if(unit_array.is_deleted(i)) continue; unitPtr = unit_array[i]; if(!unitPtr->is_visible()) continue; if(!unitPtr->selected_flag) continue; if( !config.show_ai_info && nationRecno && !unitPtr->is_nation(nationRecno) ) continue; if(unitPtr->way_point_count) { resultNodeCount = unitPtr->way_point_count; resultNode1 = unitPtr->way_point_array; // ##### begin Gilbert 12/11 #######// // char *chPtr = image_icon.get_ptr("WAYPOINT"); lineToX = (resultNode1->node_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2; lineToY = (resultNode1->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2; world.zoom_matrix->put_bitmap_clip(lineToX+chOffsetX, lineToY+chOffsetY, chPtr); // ##### begin Gilbert 12/11 #######// if(resultNodeCount>1) { resultNode2 = resultNode1+1; for(j=1; jnode_x - world.zoom_matrix->top_x_loc)*ZOOM_LOC_WIDTH + ZOOM_X1 + ZOOM_LOC_WIDTH/2; lineFromY = (resultNode2->node_y - world.zoom_matrix->top_y_loc)*ZOOM_LOC_HEIGHT + ZOOM_Y1 + ZOOM_LOC_HEIGHT/2; anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY, 0, 1); lineToX = lineFromX; lineToY = lineFromY; // ##### begin Gilbert 12/11 #######// world.zoom_matrix->put_bitmap_clip(lineToX+chOffsetX, lineToY+chOffsetY, chPtr); // ##### begin Gilbert 12/11 #######// } } } } } //------------ end of static function draw_unit_way_point_on_zoom_map -----------// //-------- Begin of function ZoomMatrix::ZoomMatrix ----------// ZoomMatrix::ZoomMatrix() : land_disp_sort_array(sizeof(DisplaySort),100), air_disp_sort_array(sizeof(DisplaySort),50), land_top_disp_sort_array(sizeof(DisplaySort), 40), land_bottom_disp_sort_array(sizeof(DisplaySort), 20) { init( ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, ZOOM_WIDTH, ZOOM_HEIGHT, ZOOM_LOC_WIDTH, ZOOM_LOC_HEIGHT, 0 ); // 0-don't create a background buffer } //---------- End of function ZoomMatrix::ZoomMatrix ----------// //---------- Begin of function ZoomMatrix::init_para ------------// void ZoomMatrix::init_para() { init_rain = 0; // #### begin Gilbert 7/10 ######// rain.clear(); rain.stop_rain(); // #### end Gilbert 7/10 ######// rain_channel_id = 0; wind_channel_id = 0; fire_channel_id = 0; last_fire_vol = 0; init_lightning = 0; init_snow = 0; last_brightness = 0; vibration = -1; } //---------- End of function ZoomMatrix::init_para ----------// //---------- Begin of function ZoomMatrix::draw ------------// // // Draw world map // void ZoomMatrix::draw() { int i=0, x, y, xLoc, yLoc, dispPower; Location* locPtr; char* nationColorArray = nation_array.nation_power_color_array; int maxXLoc = top_x_loc + disp_x_loc; // divide by 2 for world_info int maxYLoc = top_y_loc + disp_y_loc; dispPower = (world.map_matrix->map_mode == MAP_MODE_POWER && world.map_matrix->power_mode ) || power.command_id == COMMAND_BUILD_FIRM || power.command_id == COMMAND_SETTLE; sys.yield(); //----------------------------------------------------// int nationRecno, borderColor; for( y=image_y1,yLoc=top_y_loc ; yLocexplored() ) // only draw if the location has been explored { //---------- draw terrain bitmap -----------// vga_back.put_bitmap_32x32( x, y, terrain_res[locPtr->terrain_id]->bitmap_ptr ); char *overlayBitmap = terrain_res[locPtr->terrain_id]->get_bitmap(sys.frame_count /4); if( overlayBitmap) vga_back.put_bitmap_trans_decompress( x, y, overlayBitmap); #ifdef DEBUG if(debug2_enable_flag) { if(locPtr->is_coast()) { VgaBuf *activeBufBackup = Vga::active_buf; Vga::active_buf = &vga_back; font_std.put( x+24, y+20, terrain_res[locPtr->terrain_id]->average_type); Vga::active_buf = activeBufBackup; } } #endif // --------- draw dirt block --------// if( locPtr->has_dirt() ) { dirt_array[locPtr->dirt_recno()]->draw_block(xLoc,yLoc); } if(terrain_res[locPtr->terrain_id]->can_snow() ) { if( config.snow_ground==1 && snow_ground_array.snow_thick > 0) { vga_back.snow_32x32(x,y, snowSeed+xLoc, 0xffff - snow_ground_array.snow_thick); } if( config.snow_ground==2) { int snowMapId = snow_ground_array.has_snow(xLoc,yLoc); if( snowMapId ) { snow_res[snowMapId]->draw_at(xLoc*ZOOM_LOC_WIDTH+ZOOM_LOC_WIDTH/2, yLoc*ZOOM_LOC_HEIGHT+ZOOM_LOC_HEIGHT/2); } } } // --------- draw hill square --------// if( locPtr->has_hill() ) { if( locPtr->hill_id2()) hill_res[locPtr->hill_id2()]->draw(xLoc,yLoc,1); hill_res[locPtr->hill_id1()]->draw(xLoc, yLoc,1); } //---------- if in power map mode -----------// if( dispPower && (nationRecno=locPtr->power_nation_recno) > 0 ) { vga_back.pixelize_32x32( x, y, nationColorArray[nationRecno] ); borderColor = nationColorArray[nationRecno] + 1; if( yLoc==0 || get_loc(xLoc, yLoc-1)->power_nation_recno!=nationRecno ) vga_back.bar( x, y, x+31, y, borderColor ); if( yLoc==MAX_WORLD_Y_LOC-1 || get_loc(xLoc, yLoc+1)->power_nation_recno!=nationRecno ) vga_back.bar( x, y+31, x+31, y+31, borderColor ); if( xLoc==0 || get_loc(xLoc-1, yLoc)->power_nation_recno!=nationRecno ) vga_back.bar( x, y, x, y+31, borderColor ); if( xLoc==MAX_WORLD_X_LOC-1 || get_loc(xLoc+1, yLoc)->power_nation_recno!=nationRecno ) vga_back.bar( x+31, y, x+31, y+31, borderColor ); } //--------- draw raw material icon ---------// if( locPtr->has_site() && locPtr->walkable(3) ) // don't display if a building/object has already been built on the location site_array[locPtr->site_recno()]->draw(x, y); //----- draw grids, for debugging only -----// #ifdef DEBUG if(debug2_enable_flag) { vga_back.bar( x, y, x+31, y, V_WHITE ); vga_back.bar( x, y, x, y+31, V_WHITE ); // display x, y location if(!(xLoc%5) && !(yLoc%5)) { VgaBuf *activeBufBackup = Vga::active_buf; Vga::active_buf = &vga_back; font_std.put( x+4, y+3, xLoc ); font_std.put( x+4, y+15, yLoc ); Vga::active_buf = activeBufBackup; } } #endif } } } sys.yield(); //---------------------------------------------------// if( save_image_buf ) { vga_back.read_bitmap( image_x1, image_y1, image_x2, image_y2, save_image_buf ); just_drawn_flag = 1; } } //------------ End of function ZoomMatrix::draw ------------// //---------- Begin of function ZoomMatrix::draw_white_site ------------// // void ZoomMatrix::draw_white_site() { int i=0, x, y, xLoc, yLoc; Location* locPtr; int maxXLoc = top_x_loc + disp_x_loc; // divide by 2 for world_info int maxYLoc = top_y_loc + disp_y_loc; //------- draw occupied locations in whie ---------// for( y=image_y1,yLoc=top_y_loc ; yLochas_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA) || locPtr->has_unit(UNIT_AIR)) vga_back.bar( x, y, x+31, y+31, V_WHITE ); } } } //------------ End of function ZoomMatrix::draw_white_site ------------// //---------- Begin of function ZoomMatrix::draw_frame -----------// // void ZoomMatrix::draw_frame() { draw_objects(); draw_weather_effects(); draw_build_marker(); if(config.blacken_map && config.fog_of_war) blacken_fog_of_war(); else if( !config.explore_whole_map ) blacken_unexplored(); disp_text(); } //----------- End of function ZoomMatrix::draw_frame ------------// //---------- Begin of function ZoomMatrix::draw_weather_effects -----------// // void ZoomMatrix::draw_weather_effects() { //---------- Earthquake -----------// if( weather.is_quake() ) { if(vibration == -1) { // start of an earthquake vibration = weather.quake_rate(top_x_loc+disp_x_loc/2, top_y_loc+disp_y_loc/2)*16/100; if( config.sound_effect_flag && config.earthquake_audio) { RelVolume r(config.earthquake_volume,0); audio.play_long_wav( DIR_SOUND"QUAKE.WAV", DsVolume(r) ); } } int vPitch = vga_back.buf_pitch(); char *destBitmap = vga_back.buf_ptr() + ZOOM_Y1 * vPitch + ZOOM_X1; char *srcBitmap = destBitmap + vibration * vPitch; int lineCount = ZOOM_HEIGHT - vibration; // shift back buffer up if( vibration ) { if( config.earthquake_visual) { for(int lineRun = 0; lineRun < lineCount; ++lineRun) { memcpy(destBitmap, srcBitmap, ZOOM_WIDTH); destBitmap += vPitch; srcBitmap += vPitch; } } vibration = 0; } else { vibration = weather.quake_rate(top_x_loc+disp_x_loc/2, top_y_loc+disp_y_loc/2)*16/100; } } else { vibration = -1; } //---------- raining --------// short newRainScale = weather.rain_scale(); if( newRainScale != init_rain ) { // BUGHERE : did not handle, wind change (direction/speed) during a rain if( newRainScale) { rain.start_rain(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, newRainScale, weather.wind_speed()*sin(weather.wind_direct_rad())/100.0); // turn on rain noise int relVolume = config.rain_volume + newRainScale; if( relVolume > 100) relVolume = 100; if( rain_channel_id == 0) // from no rain to rain { if( config.sound_effect_flag && config.rain_audio) { RelVolume r(relVolume,0); rain_channel_id = audio.play_loop_wav(DIR_SOUND"RAIN.WAV",11008*2, DsVolume(r)); } } else { // changing rain if( config.sound_effect_flag && config.rain_audio) { RelVolume r(relVolume,0); audio.volume_loop_wav(rain_channel_id, DsVolume(r)); } else { // can't stop rain audio immediately // but at least stop it when rain change audio.stop_loop_wav(rain_channel_id); rain_channel_id = 0; } } } else { // rain stop, rain sound fade out rain.stop_rain(); if( rain_channel_id ) { audio.fade_out_loop_wav(rain_channel_id, 10); } } init_rain = newRainScale; } else { // rain stopped, check rain sound fade out if( newRainScale == 0 && rain_channel_id ) { DsVolume dsVolume(audio.get_loop_wav_volume(rain_channel_id)); AbsVolume absVolume(dsVolume); if( absVolume.abs_vol < 10 ) { audio.stop_loop_wav(rain_channel_id); rain_channel_id = 0; } } } // ##### begin Gilbert 6/9 #######// if( config.frame_speed > 0) { rain.new_drops(); if( config.rain_visual) { rain.draw_step(&vga_back); } } // ##### end Gilbert 6/9 #######// //---------- Lightning -----------// // world.lightning_signal == 0 (no lightning) // world.lightning_signal == 110, 109 (ready lightning) // 108, 107, 106, 105 (flashing), Sound effect start on 6 // 104, 103, 102, 101 (rest, decaying lighting effect ) // 100 (decrease randomly) // 99 - 1 (rest states) // see world.process unsigned long mRandom = m.get_random_seed(); if( world.lightning_signal >= 105 && world.lightning_signal <= 108) { if( !init_lightning ) { // play sound if( world.lightning_signal == 108 && config.sound_effect_flag && config.lightning_audio) { RelVolume r(config.lightning_volume,0); audio.play_long_wav(DIR_SOUND"THUNDER.WAV", DsVolume(r)); } // find the starting and ending point of the lightning lightning_x1 = Lightning::bound_x1 + 20 + short(mRandom % (Lightning::bound_x2-Lightning::bound_x1 - 40)); lightning_y1 = Lightning::bound_y1 - 50; lightning_x2 = Lightning::bound_x1 + 10 + short(mRandom % (Lightning::bound_x2-Lightning::bound_x1 - 20)); lightning_y2 = (Lightning::bound_y1+Lightning::bound_y2) / 2 + short(mRandom % ( (Lightning::bound_y2-Lightning::bound_y1) / 2)); init_lightning = 1; } lightning.init( lightning_x1, lightning_y1, lightning_x2, lightning_y2, 8); if( config.lightning_visual) lightning.draw_section(&vga_back, (109-world.lightning_signal)/4.0); } else { init_lightning = 0; } //------------ snowing ------------// short snowScale = weather.snow_scale(); if( snowScale > 0 && init_snow == 0) { long backupSeed = m.get_random_seed(); // start of snow snow.set_bound(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2); snow.init(weather.wind_speed()*sin(weather.wind_direct_rad())/200.0, snowScale+2); if( config.sound_effect_flag && config.snow_audio ) { // audio.play_wav("SNOW", config.snow_volume); } } // ###### begin Gilbert 6/9 #######// if( snowScale > 0 && config.snow_visual && config.frame_speed > 0) snow.draw_step(&vga_back); // ###### end Gilbert 6/9 #######// init_snow = snowScale; //------------ brightness, effect of lightning and cloud -------// short newBrightness; short maxBrightness = config.lightning_brightness; if( config.lightning_visual && init_lightning > 107 ) { newBrightness = -maxBrightness; } else if( config.lightning_visual && init_lightning >= 104 && init_lightning <= 107) { newBrightness = maxBrightness; } else if( config.lightning_visual && init_lightning >= 101 && init_lightning <= 103) { newBrightness = (init_lightning-100) * maxBrightness / 4; } else { newBrightness = -weather.cloud() * config.cloud_darkness ; } if( newBrightness != last_brightness ) { vga.adjust_brightness(newBrightness); last_brightness = newBrightness; } // ------------- wind sound ----------// int windSpeed = weather.wind_speed(); if( windSpeed >= 20) { int relVolume = config.wind_volume + 5 + windSpeed/4; if( relVolume > 100) relVolume = 100; if( wind_channel_id == 0) { if( config.sound_effect_flag && config.wind_audio ) { // ###### begin Gilbert 6/8 #######// // wind_channel_id = audio.play_loop_wav(DIR_SOUND"WIND.WAV",0, relVolume); RelVolume r(relVolume,0); wind_channel_id = audio.play_loop_wav(DIR_SOUND"WIND.WAV",25088*2, DsVolume(r)); // 25088 samples, 8-bit stereo, so *2 // ###### end Gilbert 6/8 #######// } } else { if( config.wind_audio) { RelVolume r(relVolume,0); audio.volume_loop_wav(wind_channel_id, DsVolume(r)); } else { audio.stop_loop_wav(wind_channel_id); wind_channel_id = 0; } } } else { if( wind_channel_id ) { if( !audio.is_loop_wav_fading(wind_channel_id) ) { audio.fade_out_loop_wav(wind_channel_id, 5); } else { DsVolume dsVolume = audio.get_loop_wav_volume(wind_channel_id); AbsVolume absVolume(dsVolume); if( absVolume.abs_vol < 5 ) { audio.stop_loop_wav(wind_channel_id); wind_channel_id =0 ; } } } } } //----------- End of function ZoomMatrix::draw_weather_effects ------------// //---------- Begin of function ZoomMatrix::draw_build_marker -----------// // void ZoomMatrix::draw_build_marker() { if( !(mouse.cur_x >= ZOOM_X1 && mouse.cur_x <= ZOOM_X2 && // if the mouse is inside the zoom area mouse.cur_y >= ZOOM_Y1 && mouse.cur_y <= ZOOM_Y2) ) { return; } // ##### begin Gilbert 24/10 #######// if( power.win_opened ) return; // ##### end Gilbert 24/10 #######// //------- COMMAND_GOD_CAST_POWER --------// else if( power.command_id == COMMAND_GOD_CAST_POWER ) { draw_god_cast_range(); return; } //----------------------------------------------// int xLoc = (mouse.cur_x-ZOOM_X1)/ZOOM_LOC_WIDTH; int yLoc = (mouse.cur_y-ZOOM_Y1)/ZOOM_LOC_HEIGHT; int locWidth, locHeight, validAction; Location* locPtr = world.get_loc(top_x_loc+xLoc, top_y_loc+yLoc); //------- if it's in firm building mode now ----// if( power.command_id == COMMAND_BUILD_FIRM ) { FirmInfo* firmInfo = firm_res[power.command_para]; locWidth = firmInfo->loc_width; locHeight = firmInfo->loc_height; validAction = world.can_build_firm( top_x_loc+xLoc, top_y_loc+yLoc, power.command_para, unit_array.selected_recno ); } //------- if it's in settling mode now ----// else if( power.command_id == COMMAND_SETTLE && unit_array.selected_recno ) { // assign to an existing town Unit* selectedUnit = unit_array[ unit_array.selected_recno ]; if( locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno == selectedUnit->nation_recno ) return; // don't draw the settling mask. locWidth = STD_TOWN_LOC_WIDTH; locHeight = STD_TOWN_LOC_HEIGHT; validAction = world.can_build_town( top_x_loc+xLoc, top_y_loc+yLoc, unit_array.selected_recno ); } //------- COMMAND_BUILD_WALL --------// else if( power.command_id == COMMAND_BUILD_WALL ) { // see also World::build_wall_tile locWidth = 1; locHeight = 1; Location *locPtr; validAction = world.can_build_wall(top_x_loc+xLoc, top_y_loc+yLoc, nation_array.player_recno) || ( (locPtr=get_loc(top_x_loc+xLoc, top_y_loc+yLoc))->is_wall() && locPtr->is_wall_destructing() && world.can_destruct_wall(top_x_loc+xLoc, top_y_loc+yLoc, nation_array.player_recno) ); } //------- COMMAND_DESTRUCT_WALL --------// else if( power.command_id == COMMAND_DESTRUCT_WALL ) { locWidth = 1; locHeight = 1; // see also World::destruct_wall_tile validAction = world.can_destruct_wall(top_x_loc+xLoc, top_y_loc+yLoc, nation_array.player_recno) && get_loc(top_x_loc+xLoc, top_y_loc+yLoc)->is_wall_creating() ; } else return; //---------- draw an highlight area -----------// int x1 = ZOOM_X1 + xLoc * ZOOM_LOC_WIDTH; int y1 = ZOOM_Y1 + yLoc * ZOOM_LOC_HEIGHT; int x2 = ZOOM_X1 + (xLoc+locWidth) * ZOOM_LOC_WIDTH -1; int y2 = ZOOM_Y1 + (yLoc+locHeight) * ZOOM_LOC_HEIGHT-1; int pixelColor; if( validAction ) #ifdef AMPLUS pixelColor = anim_line.get_series_color_array(-1)[2]; #else pixelColor = V_WHITE; #endif else pixelColor = V_BLACK; vga_back.pixelize( x1, y1, min(x2,ZOOM_X2), min(y2,ZOOM_Y2), pixelColor ); //------- draw lines connected to towns and firms ---------// if( validAction ) { if( power.command_id==COMMAND_BUILD_FIRM ) { world.draw_link_line( power.command_para, 0, top_x_loc+xLoc, top_y_loc+yLoc, top_x_loc+xLoc+locWidth-1, top_y_loc+yLoc+locHeight-1 ); } else if( power.command_id==COMMAND_SETTLE ) { world.draw_link_line( 0, 0, top_x_loc+xLoc, top_y_loc+yLoc, top_x_loc+xLoc+locWidth-1, top_y_loc+yLoc+locHeight-1 ); } } } //----------- End of function ZoomMatrix::draw_build_marker ------------// //---------- Begin of function ZoomMatrix::draw_god_cast_range -----------// // void ZoomMatrix::draw_god_cast_range() { #define GOD_CAST_RANGE_COLOR V_WHITE int xLoc, yLoc, centerY, t; int x1, y1, x2, y2; Location* locPtr; Unit* unitPtr = unit_array[power.command_unit_recno]; GodInfo* godInfo = god_res[ ((UnitGod*)unitPtr)->god_id ]; xLoc = (mouse.cur_x-ZOOM_X1)/ZOOM_LOC_WIDTH; yLoc = (mouse.cur_y-ZOOM_Y1)/ZOOM_LOC_HEIGHT; int xLoc1 = xLoc - godInfo->cast_power_range + 1; int yLoc1 = yLoc - godInfo->cast_power_range + 1; int xLoc2 = xLoc + godInfo->cast_power_range - 1; int yLoc2 = yLoc + godInfo->cast_power_range - 1; centerY = (yLoc1+yLoc2) / 2; //----- pixelize the area within which the power can casted ----// for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { t=abs(yLoc-centerY)/2; for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++, locPtr++ ) { if( xLoc>=0 && xLoc=0 && yLoc0 ; i-- ) { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( !world.get_loc(townPtr->center_x, townPtr->center_y)->explored() ) continue; y = (townPtr->abs_y1+townPtr->abs_y2)/2; dispSpy = config.disp_spy_sign && townPtr->has_player_spy(); if( config.disp_town_name && dispSpy ) y-=7; if( config.disp_town_name ) { String str(townPtr->town_name()); put_center_text( (townPtr->abs_x1+townPtr->abs_x2)/2, y, str ); y+=14; } if( dispSpy ) put_center_text( (townPtr->abs_x1+townPtr->abs_x2)/2, y, "(Spy)" ); } } //------ firms -------// if( config.disp_spy_sign ) { Firm* firmPtr; for( int i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; if( firmPtr->player_spy_count ) { put_center_text( (firmPtr->abs_x1+firmPtr->abs_x2)/2, (firmPtr->abs_y1+firmPtr->abs_y2)/2, "(Spy)" ); } } } } //----------- End of function ZoomMatrix::disp_text ------------// //---------- Begin of function ZoomMatrix::put_center_text -----------// // // x, y - center of the absolute position where the text should be put. // str - the display string. // void ZoomMatrix::put_center_text(int x, int y, char* str) { str = translate.process(str); const unsigned int TEMP_BUFFER_SIZE = 0x2000; char tempBuffer[TEMP_BUFFER_SIZE]; short w = font_news.text_width(str); // ###### begin Gilbert 15/10 #######// // short h = font_news.text_height(); short h = font_news.max_font_height; // ###### end Gilbert 15/10 #######// if( w * h + 2*sizeof(short) <= TEMP_BUFFER_SIZE ) { char *bufferPtr = tempBuffer; *(short *)bufferPtr = w; bufferPtr += sizeof(short); *(short *)bufferPtr = h; bufferPtr += sizeof(short); memset( bufferPtr, TRANSPARENT_CODE, w * h ); font_news.put_to_buffer(bufferPtr, w, 0, 0, str); // test clipping against ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2 int x1 = x - World::view_top_x - w / 2 ; int x2 = x1 + w - 1; int y1 = y - World::view_top_y - h / 2; int y2 = y1 + h - 1; if( x1 < ZOOM_X2 && x2 >= 0 && y1 < ZOOM_HEIGHT && y2 >= 0) { if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT ) { vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, tempBuffer, max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1); } else { vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, tempBuffer ); } } } } //----------- End of function ZoomMatrix::put_center_text ------------// //---------- Begin of function ZoomMatrix::blacken_unexplored -----------// // void ZoomMatrix::blacken_unexplored() { //----------- black out unexplored area -------------// int leftLoc = top_x_loc; int topLoc = top_y_loc; int rightLoc = leftLoc + disp_x_loc - 1; int bottomLoc = topLoc + disp_y_loc - 1; int scrnY, scrnX; // screen coordinate int x, y; // x,y Location Location *thisRowLoc, *northRowLoc, *southRowLoc; scrnY = ZOOM_Y1; for( y = topLoc; y <= bottomLoc; ++y, scrnY += ZOOM_LOC_HEIGHT) { thisRowLoc = get_loc(leftLoc, y); northRowLoc = y > 0 ? get_loc(leftLoc, y-1) : thisRowLoc; southRowLoc = y+1 < max_y_loc ? get_loc(leftLoc, y+1): thisRowLoc; // load north bit into bit0, north west bit into bit 1 int northRow = northRowLoc->explored() ? 1 : 0; int thisRow = thisRowLoc->explored() ? 1 : 0; int southRow = southRowLoc->explored() ? 1 : 0; if( leftLoc > 0) { northRow |= (northRowLoc-1)->explored() ? 2 : 0; thisRow |= (thisRowLoc -1)->explored() ? 2 : 0; southRow |= (southRowLoc-1)->explored() ? 2 : 0; } else { // replicate bit 0 to bit 1; northRow *= 3; thisRow *= 3; southRow *= 3; } scrnX = ZOOM_X1; for( x = leftLoc; x <= rightLoc; ++x, scrnX += ZOOM_LOC_WIDTH ) { if( x+1 < max_x_loc) { northRow = (northRow << 1) | ((++northRowLoc)->explored() ? 1 : 0); thisRow = (thisRow << 1) | ((++thisRowLoc )->explored() ? 1 : 0); southRow = (southRow << 1) | ((++southRowLoc)->explored() ? 1 : 0); } else { // replicate bit 1 northRow = (northRow << 1) | (northRow & 1); thisRow = (thisRow << 1) | (thisRow & 1); southRow = (southRow << 1) | (southRow & 1); } // optional // northRow &= 7; // thisRow &= 7; // southRow &= 7; // ---------- Draw mask to vgabuf --------// if( thisRow & 2) // center square { explored_mask.draw(scrnX, scrnY, northRow, thisRow, southRow); } else { vga_back.black_32x32(scrnX, scrnY); } } } } //----------- End of function ZoomMatrix::blacken_unexplored ------------// //---------- Begin of function ZoomMatrix::blacken_fog_of_war -----------// // void ZoomMatrix::blacken_fog_of_war() { int leftLoc = top_x_loc; int topLoc = top_y_loc; int rightLoc = leftLoc + disp_x_loc - 1; int bottomLoc = topLoc + disp_y_loc - 1; int scrnY, scrnX; // screen coordinate int x, y; // x,y Location Location *thisRowLoc, *northRowLoc, *southRowLoc; if( config.fog_mask_method == 1) { // use fast method scrnY = ZOOM_Y1; for( y = topLoc; y <= bottomLoc; ++y, scrnY += ZOOM_LOC_HEIGHT) { thisRowLoc = get_loc(leftLoc,y); scrnX = ZOOM_X1; for( x = leftLoc; x <= rightLoc; ++x, scrnX += ZOOM_LOC_WIDTH, ++thisRowLoc ) { if( !thisRowLoc->explored() ) { vga_back.bar(scrnX, scrnY, scrnX+ZOOM_LOC_WIDTH-1, scrnY+ZOOM_LOC_HEIGHT-1, 0); } else { unsigned char v = thisRowLoc->visibility(); if( v < MAX_VISIT_LEVEL-7) { // more visible draw 1/4 tone vga_back.pixelize_32x32(scrnX+1, scrnY, 0); vga_back.pixelize_32x32(scrnX, scrnY+1, 0); } // for visibility >= MAX_VISIT_LEVEL, draw nothing } } } } else { // use slow method scrnY = ZOOM_Y1; for( y = topLoc; y <= bottomLoc; ++y, scrnY += ZOOM_LOC_HEIGHT) { thisRowLoc = get_loc(leftLoc, y); northRowLoc = y > 0 ? get_loc(leftLoc, y-1) : thisRowLoc; southRowLoc = y+1 < max_y_loc ? get_loc(leftLoc, y+1): thisRowLoc; // load north bit into bit0, north west bit into bit 1 // [2] = west, [1] = this, [0] = east unsigned char northRow[3]; unsigned char thisRow[3]; unsigned char southRow[3]; northRow[0] = northRowLoc->visibility(); thisRow[0] = thisRowLoc->visibility(); southRow[0] = southRowLoc->visibility(); if( leftLoc > 0) { northRow[1] = (northRowLoc-1)->visibility(); thisRow[1] = (thisRowLoc-1)->visibility(); southRow[1] = (southRowLoc-1)->visibility(); } else { // copy [0] to [1] northRow[1] = northRow[0]; thisRow[1] = thisRow[0]; southRow[1] = southRow[0]; } scrnX = ZOOM_X1; for( x = leftLoc; x <= rightLoc; ++x, scrnX += ZOOM_LOC_WIDTH ) { // shift to west northRow[2] = northRow[1]; northRow[1] = northRow[0]; thisRow[2] = thisRow[1]; thisRow[1] = thisRow[0]; southRow[2] = southRow[1]; southRow[1] = southRow[0]; // shift in east squares of each row if( x+1 < max_x_loc) { northRow[0] = (++northRowLoc)->visibility(); thisRow[0] = (++thisRowLoc)->visibility(); southRow[0] = (++southRowLoc)->visibility(); } // if on the east of the map, simply replicate the eastest square // ---------- Draw mask to vgabuf --------// unsigned char midNorthRow[3]; unsigned char midThisRow[3]; unsigned char midSouthRow[3]; midThisRow[2] = min( thisRow[2], thisRow[1]); midThisRow[0] = min( thisRow[0], thisRow[1]); midNorthRow[2] = min( min(northRow[2], northRow[1]), midThisRow[2] ); midNorthRow[1] = min( northRow[1], thisRow[1]); midNorthRow[0] = min( min(northRow[0], northRow[1]), midThisRow[0] ); midSouthRow[2] = min( min(southRow[2], southRow[1]), midThisRow[2] ); midSouthRow[1] = min( southRow[1], thisRow[1]); midSouthRow[0] = min( min(southRow[0], southRow[1]), midThisRow[0] ); unsigned char midMean = ((int) thisRow[0] + thisRow[2] + northRow[0] + northRow[1] + northRow[2] + southRow[0] + southRow[1] + southRow[2] ) /8; midThisRow[1] = min(thisRow[1], midMean ); vga_back.fog_remap(scrnX, scrnY, (char **)explored_mask.brightness_table->get_table_array(), midNorthRow, midThisRow, midSouthRow); } } } } //---------- End of function ZoomMatrix::blacken_fog_of_war -----------// //--------- Begin of function ZoomMatrix::draw_objects ---------// // // Draw the following types of objects on the zoom map in a sorted order. // // 1. Firms // 2. Town sections // 3. Sprites // void ZoomMatrix::draw_objects() { //----- get the location of the zoom area ------// const int DRAW_OUTSIDE = 3; int zoomXLoc1 = world.zoom_matrix->top_x_loc - DRAW_OUTSIDE; int zoomYLoc1 = world.zoom_matrix->top_y_loc - DRAW_OUTSIDE; int zoomXLoc2 = world.zoom_matrix->top_x_loc + world.zoom_matrix->disp_x_loc - 1 + DRAW_OUTSIDE; int zoomYLoc2 = world.zoom_matrix->top_y_loc + world.zoom_matrix->disp_y_loc - 1 + DRAW_OUTSIDE; if( zoomXLoc1 < 0) zoomXLoc1 = 0; if( zoomYLoc1 < 0) zoomYLoc1 = 0; if( zoomXLoc2 >= max_x_loc) zoomXLoc2 = max_x_loc-1; if( zoomYLoc2 >= max_y_loc) zoomYLoc2 = max_y_loc-1; //---- add the objects on the zoom area to land_disp_sort_array in a sorted display order ---// int xLoc, yLoc; Location* locPtr; DisplaySort displaySort; Unit* unitPtr; Firm* firmPtr; Town* townPtr; PlantBitmap* plantBitmap; int innerY, drawY; int dispFire = 0; // ####### begin Gilbert 31/7 ########// char pMobileType; // pointing mobileType Location* pLoc = power.test_detect(mouse.cur_x, mouse.cur_y, &pMobileType); // ####### end Gilbert 31/7 ########// for( yLoc=zoomYLoc1 ; yLoc<=zoomYLoc2 ; yLoc++ ) { locPtr = world.get_loc(zoomXLoc1,yLoc); for( xLoc=zoomXLoc1 ; xLoc<=zoomXLoc2 ; xLoc++, locPtr++ ) { //------- if there is an unit in the air --------// if( locPtr->has_unit(UNIT_AIR) ) { memset(&displaySort, 0, sizeof(displaySort)); unitPtr = unit_array[locPtr->air_cargo_recno]; unitPtr->update_abs_pos(); // update its absolute position displaySort.object_type = OBJECT_UNIT; displaySort.object_recno = locPtr->air_cargo_recno; displaySort.object_y2 = unitPtr->abs_y2; if(pLoc == locPtr && pMobileType == UNIT_AIR) { displaySort.object_type = OBJECT_POINTED_UNIT; // BUGHERE : this part may fails if sprite size > 1x1 } if( !unitPtr->is_shealth() ) { if( unitPtr->sprite_info->loc_width > 1 ) { if( xLoc==max( unitPtr->next_x_loc(), zoomXLoc1 ) && yLoc==max( unitPtr->next_y_loc(), zoomYLoc1 ) ) { air_disp_sort_array.linkin(&displaySort); } } else { air_disp_sort_array.linkin(&displaySort); } } } //------- if there is an unit on the land or sea -------// if( locPtr->has_unit(UNIT_LAND) || locPtr->has_unit(UNIT_SEA) ) { memset(&displaySort, 0, sizeof(displaySort)); unitPtr = unit_array[locPtr->cargo_recno]; unitPtr->update_abs_pos(); // update its absolute position displaySort.object_type = OBJECT_UNIT; displaySort.object_recno = locPtr->cargo_recno; displaySort.object_y2 = unitPtr->abs_y2; if( pLoc == locPtr && (pMobileType == UNIT_LAND || pMobileType == UNIT_SEA)) { displaySort.object_type = OBJECT_POINTED_UNIT; // BUGHERE : this part may fails if sprite size > 1x1 } if( !unitPtr->is_shealth() ) { if( unitPtr->sprite_info->loc_width > 1 ) { if( xLoc==max( unitPtr->next_x_loc(), zoomXLoc1 ) && yLoc==max( unitPtr->next_y_loc(), zoomYLoc1 ) ) { land_disp_sort_array.linkin(&displaySort); } } else { land_disp_sort_array.linkin(&displaySort); } } } //--------- if there is a firm on the location --------// else if( locPtr->is_firm() ) { memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_FIRM; displaySort.object_recno = locPtr->firm_recno(); firmPtr = firm_array[locPtr->firm_recno()]; displaySort.object_y2 = firmPtr->abs_y2; if( xLoc==max( firmPtr->loc_x1, zoomXLoc1 ) && yLoc==max( firmPtr->loc_y1, zoomYLoc1 ) ) { land_bottom_disp_sort_array.linkin(&displaySort); land_disp_sort_array.linkin(&displaySort); } } //------ if there is a town section on the location -----// else if( locPtr->is_town() ) { memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_TOWN; displaySort.object_recno = locPtr->town_recno(); townPtr = town_array[locPtr->town_recno()]; displaySort.object_y2 = townPtr->abs_y2; if( xLoc==max( townPtr->loc_x1, zoomXLoc1 ) && yLoc==max( townPtr->loc_y1, zoomYLoc1 ) ) { land_bottom_disp_sort_array.linkin(&displaySort); land_disp_sort_array.linkin(&displaySort); } } //------ if there is a plant on the location -----// else if( locPtr->is_plant() ) { memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_PLANT; displaySort.object_recno = locPtr->plant_id(); plantBitmap = plant_res.get_bitmap(locPtr->plant_id()); innerY = locPtr->plant_inner_y(); drawY = yLoc*ZOOM_LOC_HEIGHT + innerY-ZOOM_LOC_HEIGHT/2 + plantBitmap->offset_y + plantBitmap->bitmap_height - 1; displaySort.object_y2 = drawY; displaySort.x_loc = xLoc; displaySort.y_loc = yLoc; land_disp_sort_array.linkin(&displaySort); } //------ if there is a wall on the location -------// else if( locPtr->is_wall() ) { memset(&displaySort, 0, sizeof(displaySort)); WallInfo *wallInfo = wall_res[locPtr->wall_id()]; displaySort.object_type = OBJECT_WALL; // high byte of object_recno stores nation_recno // low byte of object_recno stores wall_id displaySort.object_recno = wallInfo->draw_wall_id; if( locPtr->power_nation_recno > 0) { displaySort.object_recno += locPtr->power_nation_recno << 8; } if( ! wallInfo->is_gate()) { // -------- non-gate square displaySort.object_y2 = yLoc* ZOOM_LOC_HEIGHT +ZOOM_LOC_HEIGHT-1; displaySort.x_loc = xLoc * ZOOM_LOC_WIDTH; displaySort.y_loc = yLoc * ZOOM_LOC_HEIGHT; land_disp_sort_array.linkin(&displaySort); } else { // -------- gate square ---------// displaySort.object_y2 = yLoc * ZOOM_LOC_HEIGHT + wallInfo->offset_y + wallInfo->bitmap_height() -1; displaySort.x_loc = xLoc + wallInfo->loc_off_x; displaySort.y_loc = yLoc + wallInfo->loc_off_y; if( xLoc == max( displaySort.x_loc, zoomXLoc1) && yLoc == max( displaySort.y_loc, zoomYLoc1) ) { displaySort.x_loc = xLoc * ZOOM_LOC_WIDTH + wallInfo->offset_x; displaySort.y_loc = yLoc * ZOOM_LOC_HEIGHT + wallInfo->offset_y; land_disp_sort_array.linkin(&displaySort); } } } else if(locPtr->has_hill() && hill_res[locPtr->hill_id1()]->layer & 2 ) { memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_HILL; displaySort.object_recno = locPtr->hill_id1(); displaySort.object_y2 = (yLoc+1)*ZOOM_LOC_HEIGHT-1; displaySort.x_loc = xLoc; displaySort.y_loc = yLoc; land_disp_sort_array.linkin(&displaySort); } else if(locPtr->is_rock()) { memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_ROCK; Rock *rockPtr = rock_array[displaySort.object_recno = locPtr->rock_array_recno()]; displaySort.object_y2 = ZOOM_LOC_HEIGHT * (rockPtr->loc_y + rock_res.get_rock_info(rockPtr->rock_recno)->loc_height) -1; if( xLoc==max( rockPtr->loc_x, zoomXLoc1 ) && yLoc==max( rockPtr->loc_y, zoomYLoc1 ) ) { land_disp_sort_array.linkin(&displaySort); } } #ifdef DEBUG2 if(debug_sim_game_type!=2 && locPtr->fire_str()>0) #else if( locPtr->fire_str() > 0 ) #endif { memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_FIRE; displaySort.object_recno = locPtr->fire_str(); displaySort.object_y2 = (yLoc+1)*ZOOM_LOC_HEIGHT - ((((xLoc+13) * (yLoc+17)) % 16) & ~1); displaySort.x_loc = xLoc; displaySort.y_loc = yLoc; land_disp_sort_array.linkin(&displaySort); land_top_disp_sort_array.linkin(&displaySort); dispFire++; } } } //------ add bullet sprites to the display array -------// Bullet* bulletPtr; int i; for( i=bullet_array.size() ; i>0 ; i-- ) { if( bullet_array.is_deleted(i) ) continue; bulletPtr = bullet_array[i]; // ######### begin Gilbert 20/6 #########// if( bulletPtr->is_shealth() || bulletPtr->cur_x_loc() < zoomXLoc1 || bulletPtr->cur_x_loc() > zoomXLoc2 || bulletPtr->cur_y_loc() < zoomYLoc1 || bulletPtr->cur_y_loc() > zoomYLoc2 ) continue; // ######### end Gilbert 20/6 #########// bulletPtr->update_abs_pos(); // update its absolute position displaySort.object_type = OBJECT_BULLET; displaySort.object_recno = i; displaySort.object_y2 = bulletPtr->abs_y2; switch( bulletPtr->display_layer() ) { case AIR_DISP_LAYER_MASK: air_disp_sort_array.linkin(&displaySort); break; case LAND_BOTTOM_DISP_LAYER_MASK: land_bottom_disp_sort_array.linkin(&displaySort); break; case LAND_TOP_DISP_LAYER_MASK: land_top_disp_sort_array.linkin(&displaySort); break; case 0: case LAND_DISP_LAYER_MASK: land_disp_sort_array.linkin(&displaySort); break; default: err_here(); } } // --------- draw tornado --------// Tornado *tornadoPtr; for( i=tornado_array.size(); i > 0; i--) { if( tornado_array.is_deleted(i) ) continue; tornadoPtr = tornado_array[i]; // ######### begin Gilbert 28/5 #########// // if( tornadoPtr->is_shealth() ) if( // tornadoPtr->is_shealth() || tornadoPtr->cur_x_loc() < zoomXLoc1 || tornadoPtr->cur_x_loc() > zoomXLoc2 || tornadoPtr->cur_y_loc() < zoomYLoc1 || tornadoPtr->cur_y_loc() > zoomYLoc2 ) continue; // ######### end Gilbert 28/5 #########// tornadoPtr->update_abs_pos(); displaySort.object_type = OBJECT_TORNADO; displaySort.object_recno = i; displaySort.object_y2 = tornadoPtr->abs_y2; air_disp_sort_array.linkin(&displaySort); } for( i=effect_array.size(); i > 0; i--) { if( effect_array.is_deleted(i) ) continue; Effect *effectPtr = (Effect *)effect_array[i]; // ######### begin Gilbert 28/5 #########// if( effectPtr->is_shealth() || effectPtr->cur_x_loc() < zoomXLoc1 || effectPtr->cur_x_loc() > zoomXLoc2 || effectPtr->cur_y_loc() < zoomYLoc1 || effectPtr->cur_y_loc() > zoomYLoc2 ) continue; // ######### end Gilbert 28/5 #########// effectPtr->update_abs_pos(); displaySort.object_type = OBJECT_EFFECT; displaySort.object_recno = i; displaySort.object_y2 = effectPtr->abs_y2; switch( effectPtr->layer ) { case AIR_DISP_LAYER_MASK: air_disp_sort_array.linkin(&displaySort); break; case LAND_BOTTOM_DISP_LAYER_MASK: land_bottom_disp_sort_array.linkin(&displaySort); break; case LAND_TOP_DISP_LAYER_MASK: land_top_disp_sort_array.linkin(&displaySort); break; case 0: case LAND_DISP_LAYER_MASK: land_disp_sort_array.linkin(&displaySort); break; default: err_here(); } } // ###### begin Gilbert 2/10 #######// for( i=firm_die_array.size(); i > 0; i--) { if( firm_die_array.is_deleted(i) ) continue; FirmDie *firmDiePtr = (FirmDie *)firm_die_array[i]; if( firmDiePtr->loc_x2 < zoomXLoc1 || firmDiePtr->loc_x1 > zoomXLoc2 || firmDiePtr->loc_y2 < zoomYLoc1 || firmDiePtr->loc_y1 > zoomYLoc2 ) continue; //--------- if there is a dying firm on the location --------// memset(&displaySort, 0, sizeof(displaySort)); displaySort.object_type = OBJECT_FIRM_DIE; displaySort.object_recno = i; displaySort.object_y2 = firmDiePtr->loc_y2 * ZOOM_LOC_HEIGHT; land_bottom_disp_sort_array.linkin(&displaySort); land_disp_sort_array.linkin(&displaySort); } // ###### end Gilbert 2/10 #######// //---------- quicksort the array -----------// land_disp_sort_array.quick_sort( sort_display_function ); air_disp_sort_array.quick_sort( sort_display_function ); land_top_disp_sort_array.quick_sort( sort_display_function ); land_bottom_disp_sort_array.quick_sort( sort_display_function ); // ##### begin Gilbert 9/10 ######// //------------ draw unit path and objects ---------------// draw_objects_now(&land_bottom_disp_sort_array, LAND_BOTTOM_DISP_LAYER_MASK); draw_unit_path_on_zoom_map(LAND_DISP_LAYER_MASK); draw_objects_now(&land_disp_sort_array,LAND_DISP_LAYER_MASK); draw_objects_now(&land_top_disp_sort_array,LAND_TOP_DISP_LAYER_MASK); draw_unit_path_on_zoom_map(AIR_DISP_LAYER_MASK); draw_unit_way_point_on_zoom_map(); draw_objects_now(&air_disp_sort_array); // ##### end Gilbert 9/10 ######// //----------- clean up the array ----------// land_disp_sort_array.zap(0); // 0-don't resize the array, keep its current size air_disp_sort_array.zap(0); // 0-don't resize the array, keep its current size land_top_disp_sort_array.zap(0); land_bottom_disp_sort_array.zap(0); //----------- fire sound ----------// if(dispFire > 0) { int relVolume = 80 + dispFire/2; if( relVolume > 100) relVolume = 100; if( fire_channel_id == 0) { last_fire_vol = relVolume; RelVolume r(relVolume,0); fire_channel_id = audio.play_loop_wav( DIR_SOUND"FIRE.WAV",8447 *2, DsVolume(r)); } else if( last_fire_vol - relVolume > 2 || last_fire_vol - relVolume < 2) { last_fire_vol = relVolume; RelVolume r(relVolume,0); audio.volume_loop_wav(fire_channel_id, DsVolume(r)); } } else { if( fire_channel_id != 0) { audio.stop_loop_wav(fire_channel_id); fire_channel_id = 0; last_fire_vol = 0; } } } //----------- End of function ZoomMatrix::draw_objects -----------// //---------- Begin of function ZoomMatrix::draw_objects_now -----------// // void ZoomMatrix::draw_objects_now(DynArray* unitArray, int displayLayer) { //------------ display objects ------------// DisplaySort *displaySortPtr; Firm *firmPtr; int i, dispCount = unitArray->size(); char firstFire[FLAME_GROW_STEP]; memset( firstFire, 0, sizeof(firstFire)); int riseFirePara = 0; int needFlushFire = weather.rain_scale() + weather.snow_scale(); double hWindSpeed = weather.wind_speed()*sin(weather.wind_direct_rad()); if( hWindSpeed >= 20.0) riseFirePara = 1; else if( hWindSpeed > -20.0) riseFirePara = 0; else riseFirePara = -1; if( init_fire <= flame[FLAME_GROW_STEP-1].map_height) { for( int f = FLAME_GROW_STEP-1 ; f >= 0; --f) { if( init_fire <= flame[f].map_height) { flame[f].rise(riseFirePara); } else { break; } } init_fire++; } int dispPower = (world.map_matrix->map_mode == MAP_MODE_POWER && world.map_matrix->power_mode == 1) || power.command_id == COMMAND_BUILD_FIRM || power.command_id == COMMAND_SETTLE || power.command_id == COMMAND_BUILD_WALL; for( i=1 ; i<=dispCount ; i++ ) { if( i%10==1 ) sys.yield(); displaySortPtr = (DisplaySort*) unitArray->get(i); switch(displaySortPtr->object_type) { case OBJECT_UNIT: unit_array[displaySortPtr->object_recno]->draw(); break; case OBJECT_POINTED_UNIT: unit_array[displaySortPtr->object_recno]->draw_outlined(); break; case OBJECT_BULLET: bullet_array[displaySortPtr->object_recno]->draw(); break; case OBJECT_FIRM: firmPtr = firm_array[displaySortPtr->object_recno]; firmPtr->draw(displayLayer); break; case OBJECT_TOWN: town_array[displaySortPtr->object_recno]->draw(displayLayer); break; case OBJECT_PLANT: plant_res.get_bitmap(displaySortPtr->object_recno) ->draw(displaySortPtr->x_loc, displaySortPtr->y_loc); break; case OBJECT_ROCK: // object_recno is rockArrayRecno rock_array[displaySortPtr->object_recno]->draw(); break; case OBJECT_FIRE: { int f; // when displayLayer = 0, no fire is assumed to be drawn // pass fireDisplayerLayer as 1 to this function err_when(!displayLayer); // ------- decide bitmap to draw ---- // display flame[f], where f = (fire_str()-1) /25 f = Flame::grade( displaySortPtr->object_recno ); err_when(f >= FLAME_GROW_STEP); if( !firstFire[f]) { firstFire[f] = 1; if( displayLayer == 1) { if( needFlushFire ) flame[f].flush_point(); flame[f].rise(riseFirePara); flame[f].gen_bitmap(0xe3); // 0xb4 flame[f].mask_bottom(); } else { flame[f].mask_transparent(); } } int x1 = displaySortPtr->x_loc * ZOOM_LOC_WIDTH + Flame::offset_x(f) - World::view_top_x; int y1 = displaySortPtr->y_loc * ZOOM_LOC_HEIGHT + Flame::offset_y(f) - World::view_top_y; // ------- shift 'randomly' but even number--------- x1 += (((displaySortPtr->x_loc+11) * (displaySortPtr->y_loc+13)) % 16) & ~1; x1 -= 6; y1 -= (((displaySortPtr->x_loc+13) * (displaySortPtr->y_loc+17)) % 16) & ~1; int x2 = x1 + Flame::default_width(f) -1; int y2 = y1 + Flame::default_height(f) -1; if( x2 >= 0 && x1 < ZOOM_WIDTH && y2 >= 0 && y1 < ZOOM_HEIGHT ) { if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT ) { vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, (char *)flame[f].bitmap, max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 ); } else { vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, (char *)flame[f].bitmap ); } } } break; case OBJECT_WALL: { int nationRecno = displaySortPtr->object_recno >> 8; char *remapTable = game.get_color_remap_table(nationRecno, 0); wall_res[displaySortPtr->object_recno & 0xff]->draw_at( displaySortPtr->x_loc, displaySortPtr->y_loc, remapTable); } break; case OBJECT_TORNADO: tornado_array[displaySortPtr->object_recno]->draw(); break; case OBJECT_HILL: { short xLoc = displaySortPtr->x_loc; short yLoc = displaySortPtr->y_loc; hill_res[displaySortPtr->object_recno]->draw(xLoc, yLoc, 2); // ------ draw power, because hill covers the power colour drawn ------// int nationRecno = get_loc(xLoc, yLoc)->power_nation_recno; if( dispPower && nationRecno > 0) { int x1 = xLoc*ZOOM_LOC_WIDTH - World::view_top_x; int y1 = yLoc*ZOOM_LOC_HEIGHT - World::view_top_y; if( x1 >= 0 && y1 >= 0 && x1 < ZOOM_WIDTH - (ZOOM_LOC_WIDTH-1) && y1 < ZOOM_HEIGHT - (ZOOM_LOC_HEIGHT-1)) { vga_back.pixelize_32x32( x1 + ZOOM_X1, y1 + ZOOM_Y1, nation_array.nation_power_color_array[nationRecno] ); } } } break; // #### begin Gilbert 4/10 #######// case OBJECT_EFFECT: effect_array[displaySortPtr->object_recno]->draw(); break; case OBJECT_FIRM_DIE: firm_die_array[displaySortPtr->object_recno]->draw(displayLayer); break; // #### end Gilbert 4/10 #######// } } } //----------- End of function ZoomMatrix::draw_objects_now ------------// //---------- Begin of function ZoomMatrix::scroll -----------// // // xScroll - horizontal scroll step (negative:left, positive:right) // yScroll - vertical scroll step (negative:left, positive:right) // void ZoomMatrix::scroll(int xScroll, int yScroll) { Matrix::scroll(xScroll,yScroll); world.map_matrix->cur_x_loc = top_x_loc; world.map_matrix->cur_y_loc = top_y_loc; } //----------- End of function ZoomMatrix::scroll ------------// //------ Begin of function sort_display_function ------// // static int sort_display_function( const void *a, const void *b ) { return ((DisplaySort*)a)->object_y2 - ((DisplaySort*)b)->object_y2; } //------- End of function sort_display_function ------// //------ Begin of function ZoomMatrix::put_bitmap_clip ---------// // // Put a bitmap on the surface buffer // // x, y - the location of the bitmap, in the current screen coordination // bitmapPtr - bitmap ptr // [int] compressedFlag - whether the bitmap is compressed or not // (default: 0) // void ZoomMatrix::put_bitmap_clip(int x, int y, char* bitmapPtr, int compressedFlag) { int x2 = x + *((short*)bitmapPtr) - 1; int y2 = y + *(((short*)bitmapPtr)+1) - 1; if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 ) return; //---- only portion of the sprite is inside the view area ------// if( x < ZOOM_X1 || x2 > ZOOM_X2 || y < ZOOM_Y1 || y2 > ZOOM_Y2 ) { if( compressedFlag ) { vga_back.put_bitmap_area_trans_decompress( x, y, bitmapPtr, max(ZOOM_X1,x)-x, max(ZOOM_Y1,y)-y, min(ZOOM_X2,x2)-x, min(ZOOM_Y2,y2)-y ); } else { vga_back.put_bitmap_area_trans( x, y, bitmapPtr, max(ZOOM_X1,x)-x, max(ZOOM_Y1,y)-y, min(ZOOM_X2,x2)-x, min(ZOOM_Y2,y2)-y ); } } //---- the whole sprite is inside the view area ------// else { if( compressedFlag ) vga_back.put_bitmap_trans_decompress( x, y, bitmapPtr ); else vga_back.put_bitmap_trans( x, y, bitmapPtr ); } } //--------- End of function ZoomMatrix::put_bitmap_clip ---------// //------ Begin of function ZoomMatrix::detect_bitmap_clip ---------// // // Detect clicking on the bitmap. // // return: 0 - not detected // 1 - left clicked // 2 - right clicked // int ZoomMatrix::detect_bitmap_clip(int x, int y, char* bitmapPtr) { int x2 = x + *((short*)bitmapPtr) - 1; int y2 = y + *(((short*)bitmapPtr)+1) - 1; if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 ) return 0; //---- only portion of the sprite is inside the view area ------// // return mouse.single_click( max(ZOOM_X1,x), max(ZOOM_Y1,y), min(ZOOM_X2,x2), min(ZOOM_Y2,y2), 2 ); return mouse.any_click( max(ZOOM_X1,x), max(ZOOM_Y1,y), min(ZOOM_X2,x2), min(ZOOM_Y2,y2), 0 ) ? 1 : mouse.any_click( max(ZOOM_X1,x), max(ZOOM_Y1,y), min(ZOOM_X2,x2), min(ZOOM_Y2,y2), 1 ) ? 2 : 0; } //--------- End of function ZoomMatrix::detect_bitmap_clip ---------// //------ Begin of function ZoomMatrix::put_bitmap_remap_clip ---------// // // Put a bitmap on the surface buffer // // x, y - the location of the bitmap // bitmapPtr - bitmap ptr // [char*] colorRemapTable - color remap table // [int] compressedFlag - whether the bitmap is compressed or not // (default: 0) // void ZoomMatrix::put_bitmap_remap_clip(int x, int y, char* bitmapPtr, char* colorRemapTable, int compressedFlag) { int x2 = x + *((short*)bitmapPtr) - 1; int y2 = y + *(((short*)bitmapPtr)+1) - 1; if( x2 < ZOOM_X1 || y2 < ZOOM_Y1 || x > ZOOM_X2 || y > ZOOM_Y2 ) return; //---- only portion of the sprite is inside the view arec ------// if( x < ZOOM_X1 || x2 > ZOOM_X2 || y < ZOOM_Y1 || y2 > ZOOM_Y2 ) { if( compressedFlag ) { if( colorRemapTable ) { vga_back.put_bitmap_area_trans_remap_decompress( x, y, bitmapPtr, max(ZOOM_X1,x)-x, max(ZOOM_Y1,y)-y, min(ZOOM_X2,x2)-x, min(ZOOM_Y2,y2)-y, colorRemapTable ); } else { vga_back.put_bitmap_area_trans_decompress( x, y, bitmapPtr, max(ZOOM_X1,x)-x, max(ZOOM_Y1,y)-y, min(ZOOM_X2,x2)-x, min(ZOOM_Y2,y2)-y ); } } else { if( colorRemapTable ) { vga_back.put_bitmap_area_trans_remap( x, y, bitmapPtr, max(ZOOM_X1,x)-x, max(ZOOM_Y1,y)-y, min(ZOOM_X2,x2)-x, min(ZOOM_Y2,y2)-y, colorRemapTable ); } else { vga_back.put_bitmap_area_trans( x, y, bitmapPtr, max(ZOOM_X1,x)-x, max(ZOOM_Y1,y)-y, min(ZOOM_X2,x2)-x, min(ZOOM_Y2,y2)-y ); } } } //---- the whole sprite is inside the view area ------// else { if( compressedFlag ) { if( colorRemapTable ) vga_back.put_bitmap_trans_remap_decompress( x, y, bitmapPtr, colorRemapTable ); else vga_back.put_bitmap_trans_decompress( x, y, bitmapPtr ); } else { if( colorRemapTable ) vga_back.put_bitmap_trans_remap( x, y, bitmapPtr, colorRemapTable ); else vga_back.put_bitmap_trans( x, y, bitmapPtr ); } } } //--------- End of function ZoomMatrix::put_bitmap_remap_clip ---------//