/*
* 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 : OHILLRES.CPP
//Description : Hill resource object
//Onwership : Gilbert
#include
#include
#include
#include
#include
#include
#include
//---------- #define constant ------------//
// #define HILL_DB "HILL"
//------- Begin of function HillRes::HillRes -----------//
HillRes::HillRes()
{
init_flag=0;
}
//--------- End of function HillRes::HillRes -----------//
//---------- Begin of function HillRes::init -----------//
//
// This function must be called after a map is generated.
//
void HillRes::init()
{
deinit();
//----- open hill material bitmap resource file -------//
String str;
str = DIR_RES;
// str += "I_HILL.RES";
str += "I_HILL";
str += config.terrain_set;
str += ".RES";
res_bitmap.init_imported(str,1); // 1-read all into buffer
//------- load database information --------//
load_hill_block_info();
init_flag=1;
}
//---------- End of function HillRes::init -----------//
//---------- Begin of function HillRes::deinit -----------//
void HillRes::deinit()
{
if( init_flag )
{
mem_del(first_block_index);
mem_del(hill_block_info_array);
init_flag=0;
}
}
//---------- End of function HillRes::deinit -----------//
//------- Begin of function HillRes::load_hill_info -------//
//
void HillRes::load_hill_block_info()
{
HillBlockRec *hillBlockRec;
HillBlockInfo *hillBlockInfo;
int i;
long bitmapOffset;
//---- read in hill count and initialize hill block info array ----//
String hillDbName;
hillDbName = DIR_RES;
hillDbName += "HILL";
hillDbName += config.terrain_set;
hillDbName += ".RES";
Database hillDbObj(hillDbName, 1);
// Database *dbHill = game_set.open_db(HILL_DB); // only one database can be opened at a time
Database *dbHill = &hillDbObj;
hill_block_count = (short) dbHill->rec_count();
hill_block_info_array = (HillBlockInfo*) mem_add( sizeof(HillBlockInfo)*hill_block_count );
memset( hill_block_info_array, 0, sizeof(HillBlockInfo) * hill_block_count );
max_pattern_id = 0;
//---------- read in HILL.DBF ---------//
for( i=0 ; iread(i+1);
hillBlockInfo = hill_block_info_array+i;
hillBlockInfo->block_id = i + 1;
hillBlockInfo->pattern_id = (char) m.atoi( hillBlockRec->pattern_id, hillBlockRec->PATTERN_ID_LEN);
if( hillBlockInfo->pattern_id > max_pattern_id)
max_pattern_id = hillBlockInfo->pattern_id;
hillBlockInfo->sub_pattern_id = (char) m.atoi(hillBlockRec->sub_pattern_id, hillBlockRec->SUB_PATTERN_ID_LEN);
hillBlockInfo->special_flag = hillBlockRec->special_flag;
if( hillBlockRec->special_flag == ' ')
hillBlockInfo->special_flag = 0;
hillBlockInfo->layer = hillBlockRec->layer - '0';
hillBlockInfo->priority = (char) m.atoi( hillBlockRec->priority, hillBlockRec->PRIORITY_LEN);
hillBlockInfo->bitmap_type = hillBlockRec->bitmap_type;
hillBlockInfo->offset_x = m.atoi(hillBlockRec->offset_x, hillBlockRec->OFFSET_LEN);
hillBlockInfo->offset_y = m.atoi(hillBlockRec->offset_y, hillBlockRec->OFFSET_LEN);
memcpy( &bitmapOffset, hillBlockRec->bitmap_ptr, sizeof(long) );
hillBlockInfo->bitmap_ptr = res_bitmap.read_imported(bitmapOffset);
}
//------ build index for the first block of each pattern -------//
// e.g first block id of pattern 1 is 1
// first block id of pattern 3 is 4
// first block id of pattern 4 is 7
// last block id (which is pattern 4) is 10
// first_block_index is { 1, 4, 4, 7 };
// such that, blocks which are pattern 1 are between [1,4)
// 2 are between [4,4) i.e. not found
// 3 are between [4,7)
// 4 are between [7,11)
// see also first_block()
//
first_block_index = (short *) mem_add(sizeof(short) * max_pattern_id);
memset( first_block_index, 0, sizeof(short) * max_pattern_id);
int patternMarked = 0;
for(i = 0, hillBlockInfo = hill_block_info_array; i < hill_block_count;
++i, ++hillBlockInfo)
{
err_when( hillBlockInfo->pattern_id < patternMarked);
while(patternMarked < hillBlockInfo->pattern_id)
{
first_block_index[patternMarked] = i+1;
patternMarked++;
}
}
}
//--------- End of function HillRes::load_hill_info ---------//
//---------- Begin of function HillRes::operator[] -----------//
HillBlockInfo* HillRes::operator[](int hillBlockId)
{
err_if( hillBlockId<1 || hillBlockId>hill_block_count )
err_now( "HillRes::operator[]" );
return hill_block_info_array+(hillBlockId-1);
}
//------------ End of function HillRes::operator[] -----------//
//---------- Begin of function HillRes::first_block -----------//
short HillRes::first_block(int hillPatternId)
{
err_when(hillPatternId<1);
if(hillPatternId>max_pattern_id)
return hill_block_count+1; // return last block+1
else
return first_block_index[ hillPatternId-1];
}
//------------ End of function HillRes::first_block -----------//
// ####### begin Gilbert 28/1 #######//
//------------ Begin of function HillRes::locate -----------//
short HillRes::locate(char patternId, char subPattern, char searchPriority, char specialFlag)
{
err_when(patternId < 1 || patternId > max_pattern_id);
// ------- find the range which patternId may exist ------//
// find the start of this pattern and next pattern
short startBlockIdx = first_block(patternId);
short endBlockIdx = first_block(patternId+1);
for(short j = startBlockIdx; j < endBlockIdx; ++j)
{
HillBlockInfo *hillBlockInfo = hill_block_info_array+j-1;
if( hillBlockInfo->pattern_id == patternId &&
hillBlockInfo->sub_pattern_id == subPattern &&
hillBlockInfo->priority == searchPriority &&
hillBlockInfo->special_flag == specialFlag)
{
return j;
}
}
return 0; // not found
}
//------------ End of function HillRes::locate -----------//
//------------ Begin of function HillRes::scan -----------//
short HillRes::scan(char patternId, char searchPriority, char specialFlag, char findFirst)
{
err_when(patternId < 1 || patternId > max_pattern_id);
// ------- find the range which patternId may exist ------//
// find the start of this pattern and next pattern
short startBlockIdx = first_block(patternId);
short endBlockIdx = first_block(patternId+1);
short foundBlockId = 0;
short foundCount = 0;
for(short j = startBlockIdx; j < endBlockIdx; ++j)
{
HillBlockInfo *hillBlockInfo = hill_block_info_array+j-1;
if( hillBlockInfo->pattern_id == patternId &&
hillBlockInfo->priority == searchPriority &&
hillBlockInfo->special_flag == specialFlag)
{
if( findFirst)
return j;
if( m.random(++foundCount) == 0)
{
foundBlockId = j;
}
}
}
return foundBlockId; // not found
}
//------------ End of function HillRes::scan -----------//
// ####### end Gilbert 28/1 #######//
//------- Begin of function HillInfo::draw -----------//
//
// Draw the current hill on the map
//
void HillBlockInfo::draw(int xLoc, int yLoc, int layerMask)
{
if(!(layerMask & layer))
return;
//----------- calculate absolute positions ------------//
int absX1 = xLoc*ZOOM_LOC_WIDTH + offset_x;
int absY1 = yLoc*ZOOM_LOC_HEIGHT + offset_y;
//-------- check if the firm is within the view area --------//
int x1 = absX1 - World::view_top_x;
if( x1 <= -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 = absY1 - World::view_top_y;
if( y1 <= -bitmap_height() || y1 >= ZOOM_HEIGHT )
return;
if( bitmap_type == 'W')
{
vga_back.put_bitmap_32x32(x1+ZOOM_X1,y1+ZOOM_Y1, bitmap_ptr);
return;
}
//------- decide which approach to use for displaying -----//
int x2 = absX1 + bitmap_width() - 1 - World::view_top_x;
int y2 = absY1 + bitmap_height()- 1 - World::view_top_y;
//---- 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_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
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_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr );
}
}
//--------- End of function HillBlockInfo::draw -----------//
//------- Begin of function HillBlockInfo::draw_at -----------//
//
// Draw the hill on the zoom map, given the exact pixel position to put
// the bitmap.
//
// absX1, absY1 - the absolute base (center-bottom) coordination
// of the building.
//
// Draw the current plant on the map
//
void HillBlockInfo::draw_at(int absX1, int absY1, int layerMask)
{
if(!(layerMask & layer))
return;
//-------- check if the firm is within the view area --------//
absX1 += offset_x;
absY1 += offset_y;
int x1 = absX1 - World::view_top_x;
if( x1 <= -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 = absY1 - World::view_top_y;
if( y1 <= -bitmap_height() || y1 >= ZOOM_HEIGHT )
return;
if( bitmap_type == 'W')
{
vga_back.put_bitmap_32x32(x1+ZOOM_X1,y1+ZOOM_Y1, bitmap_ptr);
return;
}
//------- decide which approach to use for displaying -----//
int x2 = absX1 + bitmap_width() - 1 - World::view_top_x;
int y2 = absY1 + bitmap_height()- 1 - World::view_top_y;
//---- 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_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
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_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr );
}
}
//--------- End of function HillBlockInfo::draw_at -----------//