/* * 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 : OUNITDRW.CPP //Description : Object Unit Drawing routines #include #include #include #include #include #include #include #include #include #include #include #include #ifdef NO_DEBUG_UNIT #undef err_when #undef err_here #undef err_if #undef err_else #undef err_now #define err_when(cond) #define err_here() #define err_if(cond) #define err_else #define err_now(msg) #undef DEBUG #endif //--------- Begin of function Unit::draw ---------// // // update Unit::draw_outlined() also // void Unit::draw() { //--------- draw sprite on the zoom window ---------// int needMirror; SpriteFrame* spriteFrame = cur_sprite_frame(&needMirror); update_abs_pos(spriteFrame); err_when( !sprite_info->res_bitmap.init_flag ); char* bitmapPtr = sprite_info->res_bitmap.read_imported(spriteFrame->bitmap_offset); //-------- check if the sprite is inside the view area --------// int x1 = abs_x1-World::view_top_x; // the sprite's position in the view window if( x1 <= -spriteFrame->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 <= -spriteFrame->height || y1 >= ZOOM_HEIGHT ) return; //------- decide which approach to use for displaying -----// int x2 = abs_x2-World::view_top_x; int y2 = abs_y2-World::view_top_y; //------- get the color remap table for this sprite ------// char* colorRemapTable = game.get_color_remap_table(nation_recno, 0); // selected_flag); //---- only portion of the sprite is inside the view area ------// if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT ) { if( needMirror ) // if this direction needed to be mirrored { vga_back.put_bitmap_area_trans_remap_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1, colorRemapTable ); } else { vga_back.put_bitmap_area_trans_remap_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, 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 { //------ mirror-bilting for certain directions ------// if( needMirror ) // if this direction needed to be mirrored { vga_back.put_bitmap_trans_remap_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, colorRemapTable ); } else { vga_back.put_bitmap_trans_remap_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, colorRemapTable ); } } //---- display additional info for selected units ----// if( selected_flag ) { draw_selected(); //---- also draw square on units that this unit is attacking ----// if( action_mode==ACTION_ATTACK_UNIT ) { if( !unit_array.is_deleted(action_para) ) unit_array[action_para]->draw_selected(); } else if( action_mode==ACTION_ATTACK_FIRM ) { if( !firm_array.is_deleted(action_para) ) firm_array[action_para]->draw_selected(); } } //--------- if the unit is a spy ---------// else if( spy_recno && (true_nation_recno() == nation_array.player_recno || config.show_ai_info) ) { int dispX1 = ZOOM_X1 + cur_x - World::view_top_x; int dispY1 = ZOOM_Y1 + cur_y - World::view_top_y - 20; int maxHitBarWidth = ZOOM_LOC_WIDTH * sprite_info->loc_width - 11; world.zoom_matrix->put_bitmap_clip(dispX1+maxHitBarWidth+1, dispY1-3, image_icon.get_ptr("U_SPY") ); } if( (is_own() || config.show_ai_info || skill.skill_id == SKILL_LEADING ) ) // || rank_id > RANK_SOLDIER) ) { if( !selected_flag && config.show_all_unit_icon ) draw_skill_icon(); } } //----------- End of function Unit::draw -----------// //--------- Begin of function Unit::draw_selected ---------// // // Draw a square around the sprite if it has been selected. // void Unit::draw_selected() { //------- determine the hit bar type -------// #define HIT_BAR_TYPE_COUNT 3 int hit_bar_color_array[HIT_BAR_TYPE_COUNT] = { 0xA8, 0xB4, 0xAC }; int hit_bar_max_array[HIT_BAR_TYPE_COUNT] = { 50, 100, 200 }; char hitBarColor; int hitBarMax; for( int i=0 ; iunit_class == UNIT_CLASS_HUMAN ) maxHitBarWidth = ZOOM_LOC_WIDTH - 11; else maxHitBarWidth = ZOOM_LOC_WIDTH; dispX1 = ZOOM_X1 + cur_x - World::view_top_x; dispY1 = ZOOM_Y1 + cur_y - World::view_top_y - 20; } else { maxHitBarWidth = ZOOM_LOC_WIDTH*2 - 22; dispX1 = ZOOM_X1 + cur_x - World::view_top_x - ZOOM_LOC_WIDTH/2 + 11; dispY1 = ZOOM_Y1 + cur_y - World::view_top_y - 20; if( mobile_type == UNIT_AIR ) dispY1 -= 20; } //----------- set other vars -----------// char* dataPtr = sys.common_data_buf; int curBarWidth = maxHitBarWidth * max_hit_points / hitBarMax; int pointX = (curBarWidth-1) * (int) hit_points / max_hit_points; // the separating point between the area with hit point and the area without err_when( max_hit_points > hitBarMax ); err_when( hit_points > max_hit_points ); *((short*)dataPtr) = curBarWidth; *(((short*)dataPtr)+1) = HIT_BAR_HEIGHT; dataPtr += sizeof(short) * 2; //--------- draw the hit bar ------------// // IMGinit( curBarWidth, HIT_BAR_HEIGHT ); IMGbar( dataPtr, curBarWidth, 0, 0, pointX, 0, hitBarColor+HIT_BAR_LIGHT_BORDER ); // top - with hit if( pointX < curBarWidth-1 ) IMGbar( dataPtr, curBarWidth, pointX+1, 0, curBarWidth-1, 0, NO_BAR_LIGHT_BORDER ); // top - without hit IMGbar( dataPtr, curBarWidth, 0, 0, 0, 2, hitBarColor+HIT_BAR_LIGHT_BORDER ); // left - with hit IMGbar( dataPtr, curBarWidth, 1, 2, pointX, 2, hitBarColor+HIT_BAR_DARK_BORDER ); // bottom - with hit if( pointX < curBarWidth-1 ) IMGbar( dataPtr, curBarWidth, pointX+1, 2, curBarWidth-1, 2, NO_BAR_DARK_BORDER ); // bottom - without hit if( pointX == curBarWidth - 1 ) IMGbar( dataPtr, curBarWidth, curBarWidth-1, 1, curBarWidth-1, 1, hitBarColor+HIT_BAR_DARK_BORDER ); // right -with hit else IMGbar( dataPtr, curBarWidth, curBarWidth-1, 1, curBarWidth-1, 1, NO_BAR_DARK_BORDER ); // right -without hit IMGbar( dataPtr, curBarWidth, 1, 1, min(pointX,curBarWidth-2), 1, hitBarColor+HIT_BAR_BODY ); // bar body if( pointX < curBarWidth - 2 ) IMGbar( dataPtr, curBarWidth, pointX+1, 1, curBarWidth-2, 1, NO_BAR_BODY ); // bar body // IMGinit( VGA_WIDTH, VGA_HEIGHT ); //--------- display the bar now ---------// world.zoom_matrix->put_bitmap_clip(dispX1, dispY1, sys.common_data_buf); //----- display skill/rank icon (only for own units) -----// if( is_own() || config.show_ai_info || skill.skill_id == SKILL_LEADING || rank_id > RANK_SOLDIER ) { draw_skill_icon(); } } //----------- End of function Unit::draw_selected -----------// //----------- Begin of function Unit::draw_skill_icon ----------// void Unit::draw_skill_icon() { if( !race_id ) // only for human units return; int maxHitBarWidth, dispX1, dispY1; if( mobile_type == UNIT_LAND ) { if( unit_res[unit_id]->unit_class == UNIT_CLASS_HUMAN ) maxHitBarWidth = ZOOM_LOC_WIDTH - 11; else maxHitBarWidth = ZOOM_LOC_WIDTH; dispX1 = ZOOM_X1 + cur_x - World::view_top_x; dispY1 = ZOOM_Y1 + cur_y - World::view_top_y - 20; } else { maxHitBarWidth = ZOOM_LOC_WIDTH*2 - 22; dispX1 = ZOOM_X1 + cur_x - World::view_top_x - ZOOM_LOC_WIDTH/2 + 11; dispY1 = ZOOM_Y1 + cur_y - World::view_top_y - 20; if( mobile_type == UNIT_AIR ) dispY1 -= 20; } String str; switch( rank_id ) { case RANK_KING: str = "U_KING"; break; case RANK_GENERAL: str = "U_GENE"; break; case RANK_SOLDIER: if( skill.skill_id ) { str = "U_"; str += skill.skill_code_array[skill.skill_id-1]; } else str = ""; break; } int y=dispY1-3; if(*str) { world.zoom_matrix->put_bitmap_clip(dispX1+maxHitBarWidth+1, dispY1-3, image_icon.get_ptr(str) ); y=dispY1+10; } if( spy_recno && (true_nation_recno() == nation_array.player_recno || config.show_ai_info) ) { world.zoom_matrix->put_bitmap_clip(dispX1+maxHitBarWidth+1, y, image_icon.get_ptr("U_SPY") ); } //### begin alex 7/10 ###// /*( force_move_flag ) { if(is_own() || config.show_ai_info) world.zoom_matrix->put_bitmap_clip(dispX1, dispY1+5, image_icon.get_ptr("MEDAL1") ); }*/ //#### end alex 7/10 ####// } //----------- End of function Unit::draw_skill_icon ----------// //----------- Begin of function Unit::is_visible ----------// int Unit::is_shealth() { return config.fog_of_war && world.get_loc(next_x_loc(), next_y_loc())->visibility() < unit_res[unit_id]->shealth; } //----------- End of function Unit::is_visible ----------// //--------- Begin of function Unit::draw_outlined ---------// // void Unit::draw_outlined() { //--------- draw sprite on the zoom window ---------// int needMirror; SpriteFrame* spriteFrame = cur_sprite_frame(&needMirror); update_abs_pos(spriteFrame); err_when( !sprite_info->res_bitmap.init_flag ); char* bitmapPtr = sprite_info->res_bitmap.read_imported(spriteFrame->bitmap_offset); //-------- check if the sprite is inside the view area --------// int x1 = abs_x1-World::view_top_x; // the sprite's position in the view window if( x1 <= -spriteFrame->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 <= -spriteFrame->height || y1 >= ZOOM_HEIGHT ) return; //------- decide which approach to use for displaying -----// int x2 = abs_x2-World::view_top_x; int y2 = abs_y2-World::view_top_y; //------- get the color remap table for this sprite ------// char* colorRemapTable = game.get_color_remap_table(nation_recno, 1); //---- only portion of the sprite is inside the view area ------// if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT ) { if( needMirror ) // if this direction needed to be mirrored { vga_back.put_bitmap_area_trans_remap_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1, colorRemapTable ); } else { vga_back.put_bitmap_area_trans_remap_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, 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 { //------ mirror-bilting for certain directions ------// if( needMirror ) // if this direction needed to be mirrored { vga_back.put_bitmap_trans_remap_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, colorRemapTable ); } else { vga_back.put_bitmap_trans_remap_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr, colorRemapTable ); } } //---- display additional info for selected units ----// if( selected_flag ) { draw_selected(); //---- also draw square on units that this unit is attacking ----// if( action_mode==ACTION_ATTACK_UNIT ) { if( !unit_array.is_deleted(action_para) ) unit_array[action_para]->draw_selected(); } else if( action_mode==ACTION_ATTACK_FIRM ) { if( !firm_array.is_deleted(action_para) ) firm_array[action_para]->draw_selected(); } } //--------- if the unit is a spy ---------// else if( spy_recno && true_nation_recno() == nation_array.player_recno ) { int dispX1 = ZOOM_X1 + cur_x - World::view_top_x; int dispY1 = ZOOM_Y1 + cur_y - World::view_top_y - 20; int maxHitBarWidth = ZOOM_LOC_WIDTH * sprite_info->loc_width - 11; world.zoom_matrix->put_bitmap_clip(dispX1+maxHitBarWidth+1, dispY1-3, image_icon.get_ptr("U_SPY") ); } if( (is_own() || config.show_ai_info || skill.skill_id == SKILL_LEADING || rank_id > RANK_SOLDIER) ) { if( !selected_flag ) { draw_skill_icon(); } } } //----------- End of function Unit::draw_outlined -----------//