/* * 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 : OFIRMDRW.CPP //Description : Firm drawing routines #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //------- define static vars -------// struct Point { short x; short y; }; static Point slot_point_array[] = { { 1, 86 }, { 8, 84 }, { 15, 86 }, { 1, 79 }, { 8, 77 }, { 15, 79 }, { 1, 72 }, { 8, 70 }, { 15, 72 }, }; //------- Begin of function Firm::draw -----------// // // Draw the firm on the map // // [int] displayLayer : 1 = same layer with units (default : 1) // : 2 = layer above units // : 4 = layer below units // void Firm::draw(int displayLayer) { FirmBuild* firmBuild = firm_res.get_build(firm_build_id); // if in construction, don't draw ground unless the last construction frame if( firmBuild->ground_bitmap_recno && (!under_construction || construction_frame() >= firmBuild->under_construction_bitmap_count-1)) { firm_res.get_bitmap(firmBuild->ground_bitmap_recno) ->draw_at(loc_x1*ZOOM_LOC_WIDTH, loc_y1*ZOOM_LOC_HEIGHT, NULL, displayLayer); } if( firmBuild->animate_full_size ) { draw_full_size(displayLayer); } else { if( under_construction ) { draw_full_size(displayLayer); } else if( !is_operating() ) { FirmBuild* firmBuild = firm_res.get_build(firm_build_id); if( firm_res.get_bitmap(firmBuild->idle_bitmap_recno) ) draw_full_size(displayLayer); else { draw_frame(1, displayLayer); draw_frame(2, displayLayer); } } else { draw_frame(1, displayLayer); // the first frame is the common frame for multi-segment bitmaps draw_frame(cur_frame, displayLayer); } } } //--------- End of function Firm::draw -----------// //------- Begin of function Firm::draw_full_size -----------// // // Draw the firm on the map // void Firm::draw_full_size(int displayLayer) { FirmBuild* firmBuild = firm_res.get_build(firm_build_id); //-------- check if the firm is within the view area --------// int x1 = abs_x1 - World::view_top_x; if( x1 <= -firmBuild->max_bitmap_width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area return; int y1 = abs_y1 - World::view_top_y; if( y1 <= -firmBuild->max_bitmap_height || y1 >= ZOOM_HEIGHT ) return; //------- get the color remap table for this bitmap ------// char* colorRemapTable = game.get_color_remap_table(nation_recno, firm_array.selected_recno == firm_recno); // ######## begin Gilbert 29/10 #######// // ------ draw flags behind the building -------// if( under_construction ) { #define FLAG_WIDTH 9 #define FLAG_HEIGHT 25 char *flagBitmapPtr = image_spict.get_ptr("FLAG-S0"); int drawX = loc_x1 * ZOOM_LOC_WIDTH - world.view_top_x + ZOOM_X1; int drawY = loc_y1 * ZOOM_LOC_HEIGHT - world.view_top_y + ZOOM_Y1; world.zoom_matrix->put_bitmap_remap_clip(drawX, drawY, flagBitmapPtr, colorRemapTable, 1); // 1-the bitmap is compressed drawX = (loc_x2+1)*ZOOM_LOC_WIDTH - FLAG_WIDTH - world.view_top_x + ZOOM_X1; world.zoom_matrix->put_bitmap_remap_clip(drawX, drawY, flagBitmapPtr, colorRemapTable, 1); // 1-the bitmap is compressed } // ######## end Gilbert 29/10 #######// //---------- get the bitmap pointer ----------// FirmBitmap* firmBitmap = NULL; if( under_construction ) { int buildFraction = construction_frame(); firmBitmap = firm_res.get_bitmap(firmBuild->under_construction_bitmap_recno + buildFraction); } else if( !is_operating() ) // is_operating() is a virtual function firmBitmap = firm_res.get_bitmap(firmBuild->idle_bitmap_recno); else firmBitmap = firm_res.get_bitmap(firmBuild->first_bitmap(cur_frame)); // ------ check if the display layer is correct ---------// if( !firmBitmap || !(firmBitmap->display_layer & displayLayer) ) return; //-------- check if the firm is within the view area --------// x1 = loc_x1 * ZOOM_LOC_WIDTH - World::view_top_x + firmBitmap->offset_x; if( x1 <= -firmBitmap->width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area return; y1 = loc_y1 * ZOOM_LOC_HEIGHT - World::view_top_y + firmBitmap->offset_y; if( y1 <= -firmBitmap->height || y1 >= ZOOM_HEIGHT ) return; //------- decide which approach to use for displaying -----// int x2 = x1 + firmBitmap->width - 1; int y2 = y1 + firmBitmap->height - 1; //------- if the firm is under construction ------// if( 0 && under_construction ) { err_when( (abs_x2-abs_x1+1) * (abs_y2-abs_y1+1) > COMMON_DATA_BUF_SIZE ); //---------- decompress the image ---------// IMGremapDecompress(sys.common_data_buf, firmBitmap->bitmap_ptr, colorRemapTable); //---------- pixelize the image -----------// char* pixelPtr = sys.common_data_buf + sizeof(short) * 2; int y, bitmapWidth=abs_x2-abs_x1+1, bitmapHeight=abs_y2-abs_y1+1; int lineCount; int solidLineCount = bitmapHeight / 2 * (int) hit_points / (int) max_hit_points; int solidLinePixel = bitmapHeight / 2 * bitmapWidth * (int) hit_points / (int) max_hit_points - solidLineCount * bitmapWidth; int hitPerPixel = (int) max_hit_points / bitmapWidth / bitmapHeight / 2; for( lineCount=1, y=bitmapHeight-2 ; y>=0 ; y-=2, lineCount++ ) { if( lineCount > solidLineCount ) memset( pixelPtr+y*bitmapWidth, TRANSPARENT_CODE, bitmapWidth ); if( lineCount==solidLineCount+1 ) // the current progressing line memset( pixelPtr+y*bitmapWidth, TRANSPARENT_CODE, solidLinePixel ); } //---- only portion of the sprite is inside the view area ------// if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT ) { vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, sys.common_data_buf, max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 ); } //---- the whole sprite is inside the view area ------// else { vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, sys.common_data_buf ); } } else //----- display the normal image (not under construction) ----// { //---- only portion of the sprite is inside the view area ------// if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT ) { vga_back.put_bitmap_area_trans_remap_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, firmBitmap->bitmap_ptr, max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1, colorRemapTable ); } //---- the whole sprite is inside the view area ------// else { vga_back.put_bitmap_trans_remap_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, firmBitmap->bitmap_ptr, colorRemapTable ); } } // ######## begin Gilbert 29/10 #######// // ------ draw flags in front of the building -------// if( under_construction ) { char *flagBitmapPtr = image_spict.get_ptr("FLAG-S0"); int drawX = loc_x1 * ZOOM_LOC_WIDTH - world.view_top_x + ZOOM_X1; int drawY = (loc_y2+1) * ZOOM_LOC_HEIGHT - FLAG_HEIGHT - world.view_top_y + ZOOM_Y1; world.zoom_matrix->put_bitmap_remap_clip(drawX, drawY, flagBitmapPtr, colorRemapTable, 1); // 1-the bitmap is compressed drawX = (loc_x2+1)*ZOOM_LOC_WIDTH - FLAG_WIDTH - world.view_top_x + ZOOM_X1; world.zoom_matrix->put_bitmap_remap_clip(drawX, drawY, flagBitmapPtr, colorRemapTable, 1); // 1-the bitmap is compressed } // ######## end Gilbert 29/10 #######// } //--------- End of function Firm::draw_full_size -----------// //------- Begin of function Firm::draw_frame -----------// // // Draw a specific frame of the firm. // void Firm::draw_frame(int frameId, int displayLayer) { //---------- draw animation now ------------// FirmBuild* firmBuild = firm_res.get_build(firm_build_id); FirmBitmap* firmBitmap; int bitmapRecno, i; int firstBitmap = firmBuild->first_bitmap(frameId); int bitmapCount = firmBuild->bitmap_count(frameId); char* colorRemapTable = game.get_color_remap_table(nation_recno, firm_array.selected_recno==firm_recno); for( i=0, bitmapRecno=firstBitmap ; idraw_at(loc_x1*ZOOM_LOC_WIDTH, loc_y1*ZOOM_LOC_HEIGHT, colorRemapTable, displayLayer); } } //--------- End of function Firm::draw_frame -----------// //------- Begin of function Firm::draw_detect_link_line ---------// // // [int] actionDetect - 0 - this is a draw action // 1 - this is a detect action // (default: 0) // // return: 1 - detected // 0 - not detected // int Firm::draw_detect_link_line(int actionDetect) { if( firm_id == FIRM_INN ) // FirmInn's link is only for scan for neighbor inns quickly, the link line is not displayed return 0; //--------------------------------------// int i, firmX, firmY, townX, townY; Firm* firmPtr; Town* townPtr; FirmInfo* firmInfo = firm_res[firm_id]; //-------- set source points ----------// int srcX = ( ZOOM_X1 + (loc_x1-world.zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH + ZOOM_X1 + (loc_x2-world.zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2; int srcY = ( ZOOM_Y1 + (loc_y1-world.zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT + ZOOM_Y1 + (loc_y2-world.zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2; //------ draw lines to linked firms ---------// int lineType; char* bitmapPtr; for( i=0 ; iloc_x1-world.zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH + ZOOM_X1 + (firmPtr->loc_x2-world.zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2; firmY = ( ZOOM_Y1 + (firmPtr->loc_y1-world.zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT + ZOOM_Y1 + (firmPtr->loc_y2-world.zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2; anim_line.draw_line(&vga_back, srcX, srcY, firmX, firmY, linked_firm_enable_array[i]==LINK_EE ); //----- check if this firm can toggle link or not -----// if( !can_toggle_firm_link(firmPtr->firm_recno) ) continue; //------ if the link is switchable -------// bitmapPtr = power.get_link_icon( linked_firm_enable_array[i], nation_recno==firmPtr->nation_recno ); if( actionDetect ) { if( own_firm() && world.zoom_matrix->detect_bitmap_clip( firmX-11, firmY-11, bitmapPtr ) ) { if( linked_firm_enable_array[i] & LINK_ED ) { toggle_firm_link( i+1, 0, COMMAND_PLAYER ); se_ctrl.immediate_sound("TURN_OFF"); } else { toggle_firm_link( i+1, 1, COMMAND_PLAYER ); se_ctrl.immediate_sound("TURN_ON"); } return 1; } } else { if( nation_recno == nation_array.player_recno ) world.zoom_matrix->put_bitmap_clip( firmX-11, firmY-11, bitmapPtr ); } } //------ draw lines to linked towns ---------// for( i=0 ; iloc_x1-world.zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH + ZOOM_X1 + (townPtr->loc_x2-world.zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2; townY = ( ZOOM_Y1 + (townPtr->loc_y1-world.zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT + ZOOM_Y1 + (townPtr->loc_y2-world.zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2; if( worker_array && selected_worker_id && worker_array[selected_worker_id-1].town_recno == townPtr->town_recno ) { lineType = -1; anim_line.thick_line(&vga_back, srcX, srcY, townX, townY, linked_town_enable_array[i]==LINK_EE, lineType ); } else { lineType = 0; anim_line.draw_line(&vga_back, srcX, srcY, townX, townY, linked_town_enable_array[i]==LINK_EE, lineType ); } //----- check if this firm can toggle link or not -----// if( !can_toggle_town_link() ) continue; //--------- draw link symbol -----------// bitmapPtr = power.get_link_icon( linked_town_enable_array[i], nation_recno==townPtr->nation_recno ); if( actionDetect ) { int rc = world.zoom_matrix->detect_bitmap_clip( townX-11, townY-11, bitmapPtr ); //------ left clicking to toggle link -------// if( rc==1 && own_firm() ) { if( linked_town_enable_array[i] & LINK_ED ) { toggle_town_link( i+1, 0, COMMAND_PLAYER ); se_ctrl.immediate_sound("TURN_OFF"); } else { toggle_town_link( i+1, 1, COMMAND_PLAYER ); se_ctrl.immediate_sound("TURN_ON"); } // // update RemoteMsg::firm_toggle_link_town() // if( firm_id == FIRM_CAMP && !remote.is_enable()) { if( townPtr->nation_recno ) townPtr->update_target_loyalty(); else townPtr->update_target_resistance(); townPtr->update_camp_link(); } return 1; } //------ right clicking to move workers ------// else if( rc==2 && selected_worker_id > 0 ) { //--- only when this worker is ours ----// if( firm_res[firm_id]->live_in_town && worker_array[selected_worker_id-1].is_nation(firm_recno, nation_array.player_recno) ) { if(townPtr->population>=MAX_TOWN_POPULATION) return 0; set_worker_home_town(townPtr->town_recno, COMMAND_PLAYER); se_ctrl.immediate_sound("PULL_MAN"); return 1; } } } else { if( nation_recno == nation_array.player_recno ) world.zoom_matrix->put_bitmap_clip( townX-11, townY-11, bitmapPtr ); } } return 0; } //------- End of function Firm::draw_detect_link_line ---------// //------- Begin of function Firm::is_in_zoom_win -----------// // // Whether the firm is in the current zoom window. // int Firm::is_in_zoom_win() { FirmBuild* firmBuild = firm_res.get_build(firm_build_id); //-------- check if the firm is within the view area --------// int x1 = abs_x1 - World::view_top_x; if( x1 <= -firmBuild->max_bitmap_width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area return 0; int y1 = abs_y1 - World::view_top_y; if( y1 <= -firmBuild->max_bitmap_height || y1 >= ZOOM_HEIGHT ) return 0; return 1; } //--------- End of function Firm::is_in_zoom_win -----------// //------- Begin of function Firm::draw_selected -----------// // // Draw a square around the firm on the map. // void Firm::draw_selected() { /* //------ calculate frame coordinations ---------// FirmBuild* firmBuild = firm_res.get_build(firm_build_id); int x1 = loc_x1 * ZOOM_LOC_WIDTH; int y1 = loc_y1 * ZOOM_LOC_HEIGHT; int x2 = (loc_x1+firmBuild->loc_width) * ZOOM_LOC_WIDTH - 1; int y2 = (loc_y1+firmBuild->loc_height) * ZOOM_LOC_HEIGHT - 1; x1 = x1 - World::view_top_x + ZOOM_X1; y1 = y1 - World::view_top_y + ZOOM_Y1; x2 = x2 - World::view_top_x + ZOOM_X1; y2 = y2 - World::view_top_y + ZOOM_Y1; //------------- set frame color -------------// char frameColor; if( nation_recno == nation_array.player_recno ) frameColor = OWN_SELECT_FRAME_COLOR; else frameColor = ENEMY_SELECT_FRAME_COLOR; //------------ draw the square frame now ------------// if( m.is_touch( x1, y1, x2, y2, ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2 ) ) { //------- Only draw_selected the portion within the zoom window area ----// if( y1 >= ZOOM_Y1 ) // square top vga_back.bar( max(x1,ZOOM_X1), y1, min(x2,ZOOM_X2), y1, frameColor ); if( y2 <= ZOOM_Y2 ) // square bottom vga_back.bar( max(x1,ZOOM_X1), y2, min(x2,ZOOM_X2), y2, frameColor ); if( x1 >= ZOOM_X1 ) // square left vga_back.bar( x1, max(y1,ZOOM_Y1), x1, min(y2,ZOOM_Y2), frameColor ); if( y1 <= ZOOM_X2 ) // square left vga_back.bar( x2, max(y1,ZOOM_Y1), x2, min(y2,ZOOM_Y2), frameColor ); //------------ display hit point bar -----------// if( firm_res[firm_id]->buildable ) { x1 = x1+1; y1 = max( y2-4, ZOOM_Y1 ); x2 = x2-1; y2 = min( y2-1, ZOOM_Y2 ); if( x1<=ZOOM_X2 && x2>=ZOOM_X1 && y1<=ZOOM_Y2 && y2>=ZOOM_Y1 ) { int barWidth = (x2-x1+1) * hit_points / max_hit_points; if( hit_points > 0 && x1+barWidth-1 >= ZOOM_X1) { vga_back.bar( max(x1,ZOOM_X1), y1 , min(x1+barWidth-1,ZOOM_X2), y1, frameColor ); vga_back.bar( max(x1,ZOOM_X1), y1+1, min(x1+barWidth-1,ZOOM_X2), y2, V_GREEN ); } } } } */ //------- draw lines connected to town ---------// draw_detect_link_line(0); } //--------- End of function Firm::draw_selected -----------// //------- Begin of function Firm::draw_cargo -----------// // // Draw cargos of stock. // // cargoCount - the no. of cargos to be drawn // cargoBitmapPtr - bitmap ptr to the cargo // void Firm::draw_cargo(int cargoCount, char* cargoBitmapPtr) { //-------- check if the firm is within the view area --------// if( loc_x1 < world.zoom_matrix->top_x_loc || loc_x2 >= world.zoom_matrix->top_x_loc+ZOOM_WIDTH ) return; if( loc_y1 < world.zoom_matrix->top_y_loc || loc_y2 >= world.zoom_matrix->top_y_loc+ZOOM_HEIGHT ) return; //------ display a pile of raw materials ------// int x = ZOOM_X1 + (loc_x1-world.zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH; int y = ZOOM_Y1 + (loc_y1-world.zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT; for( int i=0 ; iput_bitmap_clip( x+slot_point_array[i].x, y+slot_point_array[i].y, cargoBitmapPtr); } } //--------- End of function Firm::draw_cargo -----------// //------- Begin of function Firm::can_toggle_town_link ---------// // int Firm::can_toggle_town_link() { return firm_id != FIRM_MARKET; // only a market cannot toggle its link as it is } //------- Begin of function Firm::can_toggle_town_link ---------// //------- Begin of function Firm::can_toggle_firm_link ---------// // int Firm::can_toggle_firm_link(int firmRecno) { Firm* firmPtr = firm_array[firmRecno]; //--- market to harbor link is determined by trade treaty ---// if( ( firm_id == FIRM_MARKET && firmPtr->firm_id == FIRM_HARBOR ) || ( firm_id == FIRM_HARBOR && firmPtr->firm_id == FIRM_MARKET ) ) { return 0; } return firm_res[firm_id]->is_linkable_to_firm(firmPtr->firm_id); } //------- End of function Firm::can_toggle_firm_link ---------// //------- Begin of function Firm::construction_frame ---------// // // return 0 to hitfirmBuild->under_construction_bitmap_count-1 // according to hit_points and max_hitpoints // int Firm::construction_frame() { err_when(!under_construction); FirmBuild* firmBuild = firm_res.get_build(firm_build_id); int r = int( hit_points * firmBuild->under_construction_bitmap_count / max_hit_points); err_when( r < 0); if( r >= firmBuild->under_construction_bitmap_count ) r = firmBuild->under_construction_bitmap_count-1; return r; } //------- End of function Firm::construction_frame ---------//