1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 // Filename    : OFIRMDIE.CPP
22 // Description : destruting firm
23 
24 
25 #include <OSTR.h>
26 #include <OFIRMRES.h>
27 #include <OFIRMDIE.h>
28 #include <OGAMESET.h>
29 #include <OGAME.h>
30 #include <ORESDB.h>
31 #include <ALL.h>
32 
33 
34 #define FIRM_BUILD_DB 	"FDBUILD"
35 #define FIRM_FRAME_DB 	"FDFRAME"
36 #define FIRM_BITMAP_DB 	"FDBITMAP"
37 
38 
39 struct FirmDieBitmap : public FirmBitmap
40 {
41 	int	bitmap_offset;		// fill bitmap_ptr, width and height before draw()
42 };
43 
FirmDieRes()44 FirmDieRes::FirmDieRes()
45 {
46 	firm_build_count = 0;
47 	firm_bitmap_count = 0;
48 	firm_build_array = NULL;
49 	firm_bitmap_array = NULL;
50 	init_flag = 0;
51 }
52 
~FirmDieRes()53 FirmDieRes::~FirmDieRes()
54 {
55 	deinit();
56 }
57 
init()58 void FirmDieRes::init()
59 {
60 	deinit();
61 
62 	//----- open firm material bitmap resource file -------//
63 
64 	String str;
65 
66 	str  = DIR_RES;
67 	str += "I_FIRMDI.RES";
68 
69 	res_bitmap.init_imported(str,0,1);		// 0 - do not read all data into buffer
70 
71 	//------- load database information --------//
72 
73 	load_bitmap_info();		// call load_firm_bitmap() first as load_firm_info() will need info loaded by load_firm_bitmap()
74 	load_build_info();
75 
76    //----------------------------------------//
77 
78 	init_flag=1;
79 }
80 
deinit()81 void FirmDieRes::deinit()
82 {
83 	if(init_flag)
84 	{
85 		mem_del(firm_build_array);
86 		mem_del(firm_bitmap_array);
87 
88 		res_bitmap.deinit();
89 
90 		init_flag = 0;
91 	}
92 }
93 
94 
95 //------- Begin of function FirmDieRes::load_firm_bitmap -------//
96 //
97 // Read in information of FDBITMAP.DBF into memory array
98 //
load_bitmap_info()99 void FirmDieRes::load_bitmap_info()
100 {
101 	FirmBitmapRec  *firmBitmapRec;
102 	FirmDieBitmap	*firmBitmap;
103 	int      		i;
104 	uint32_t			bitmapOffset;
105 	Database 		*dbFirmBitmap = game_set.open_db(FIRM_BITMAP_DB);
106 
107 	firm_bitmap_count = (short) dbFirmBitmap->rec_count();
108 	firm_bitmap_array = (FirmDieBitmap*) mem_add( sizeof(FirmDieBitmap)*firm_bitmap_count );
109 
110 	//------ read in firm bitmap info array -------//
111 
112 	memset( firm_bitmap_array, 0, sizeof(FirmDieBitmap) * firm_bitmap_count );
113 
114 	for( i=0 ; i<firm_bitmap_count ; i++ )
115 	{
116 		firmBitmapRec = (FirmBitmapRec*) dbFirmBitmap->read(i+1);
117 		firmBitmap    = firm_bitmap_array+i;
118 
119 		memcpy( &bitmapOffset, firmBitmapRec->bitmap_ptr, sizeof(uint32_t) );
120 
121 		// BUGHERE : bitmap is not yet loaded into memory, fill them before draw()
122 		firmBitmap->bitmap_ptr = NULL;
123 		firmBitmap->width  	  = 0;
124 		firmBitmap->height 	  = 0;
125 
126 		firmBitmap->offset_x = misc.atoi( firmBitmapRec->offset_x, firmBitmapRec->OFFSET_LEN );
127 		firmBitmap->offset_y = misc.atoi( firmBitmapRec->offset_y, firmBitmapRec->OFFSET_LEN );
128 
129 		firmBitmap->loc_width  = misc.atoi( firmBitmapRec->loc_width , firmBitmapRec->LOC_LEN );
130 		firmBitmap->loc_height = misc.atoi( firmBitmapRec->loc_height, firmBitmapRec->LOC_LEN );
131 		firmBitmap->display_layer = firmBitmapRec->layer - '0';
132 
133 		firmBitmap->bitmap_offset = bitmapOffset;
134 	}
135 }
136 //--------- End of function FirmDieRes::load_firm_bitmap ---------//
137 
138 
139 //------- Begin of function FirmDieRes::load_firm_build -------//
140 //
141 // Read in information of FIRM.DBF into memory array
142 //
load_build_info()143 void FirmDieRes::load_build_info()
144 {
145 	FirmBuildRec *firmBuildRec;
146 	FirmFrameRec *firmFrameRec;
147 	FirmBuild 	 *firmBuild;
148 	FirmBitmap   *firmBitmap;
149 	int      	 i, j, k, frameRecno, bitmapRecno;
150 	short			 *firstFrameArray;
151 
152 	//---- read in firm count and initialize firm info array ----//
153 
154 	Database *dbFirmBuild = game_set.open_db(FIRM_BUILD_DB);	// only one database can be opened at a time, so we read FIRM.DBF first
155 
156 	firm_build_count = (short) dbFirmBuild->rec_count();
157 	firm_build_array = (FirmBuild*) mem_add( sizeof(FirmBuild)*firm_build_count );
158 
159 	memset( firm_build_array, 0, sizeof(FirmBuild) * firm_build_count );
160 
161 	//------ allocate an array for storing firstFrameRecno -----//
162 
163 	firstFrameArray = (short*) mem_add( sizeof(short) * firm_build_count );
164 
165 	//---------- read in FDBUILD.DBF ---------//
166 
167 	for( i=0 ; i<firm_build_count ; i++ )
168 	{
169 		firmBuildRec = (FirmBuildRec*) dbFirmBuild->read(i+1);
170 		firmBuild	 = firm_build_array+i;
171 
172 		misc.rtrim_fld( firmBuild->build_code, firmBuildRec->race_code, firmBuild->BUILD_CODE_LEN );
173 
174 		firmBuild->animate_full_size = firmBuildRec->animate_full_size=='1';
175 
176 		firmBuild->race_id = misc.atoi( firmBuildRec->race_id, firmBuildRec->RACE_ID_LEN );
177 		firmBuild->frame_count = misc.atoi( firmBuildRec->frame_count, firmBuildRec->FRAME_COUNT_LEN );
178 
179 		firmBuild->under_construction_bitmap_recno = misc.atoi(firmBuildRec->under_construction_bitmap_recno, firmBuildRec->BITMAP_RECNO_LEN);
180 		firmBuild->idle_bitmap_recno = misc.atoi(firmBuildRec->idle_bitmap_recno, firmBuildRec->BITMAP_RECNO_LEN);
181 		firmBuild->ground_bitmap_recno = misc.atoi(firmBuildRec->ground_bitmap_recno, firmBuildRec->BITMAP_RECNO_LEN);
182 
183 		err_when( firmBuild->frame_count > MAX_FIRM_FRAME );
184 
185 		firstFrameArray[i] = misc.atoi( firmBuildRec->first_frame, firmBuildRec->FIRST_FRAME_LEN );
186 
187 		// BUGHERE : need to compare same Firm name and build code in firm database
188 	}
189 
190 	//-------- read in FDFRAME.DBF --------//
191 
192 	Database 	*dbFirmFrame = game_set.open_db(FIRM_FRAME_DB);
193 	int 			minOffsetX, minOffsetY;
194 	int			maxX2, maxY2;
195 
196 	for( i=0 ; i<firm_build_count ; i++ )
197 	{
198 		firmBuild  = firm_build_array+i;
199 		frameRecno = firstFrameArray[i];
200 
201 		minOffsetX = minOffsetY = 0xFFFF;
202 		maxX2 = maxY2 = 0;
203 
204 		for( j=0 ; j<firmBuild->frame_count ; j++, frameRecno++ )
205 		{
206 			firmFrameRec = (FirmFrameRec*) dbFirmFrame->read(frameRecno);
207 
208 			//------ following animation frames, bitmap sections -----//
209 
210 			firmBuild->first_bitmap_array[j] = misc.atoi( firmFrameRec->first_bitmap, firmFrameRec->FIRST_BITMAP_LEN );
211 			firmBuild->bitmap_count_array[j] = misc.atoi( firmFrameRec->bitmap_count, firmFrameRec->BITMAP_COUNT_LEN );
212 
213 			firmBuild->frame_delay_array[j] = misc.atoi( firmFrameRec->delay, firmFrameRec->DELAY_LEN );
214 
215 			//---- get the MIN offset_x, offset_y and MAX width, height ----//
216 			//
217 			// So we can get the largest area of all the frames in this building
218 			// and this will serve as a normal size setting for this building,
219 			// with variation from frame to frame
220 			//
221 			//--------------------------------------------------------------//
222 
223 			firmBitmap = firm_bitmap_array + firmBuild->first_bitmap_array[j] - 1;
224 
225 			for( k=firmBuild->bitmap_count_array[j] ; k>0 ; k--, firmBitmap++ )
226 			{
227 				if( firmBitmap->offset_x < minOffsetX )
228 					minOffsetX = firmBitmap->offset_x;
229 
230 				if( firmBitmap->offset_y < minOffsetY )
231 					minOffsetY = firmBitmap->offset_y;
232 
233 				if( firmBitmap->offset_x + firmBitmap->width > maxX2 )
234 					maxX2 = firmBitmap->offset_x + firmBitmap->width;
235 
236 				if( firmBitmap->offset_y + firmBitmap->height > maxY2 )
237 					maxY2 = firmBitmap->offset_y + firmBitmap->height;
238 			}
239 		}
240 
241 		//------- set FirmBuild Info -------//
242 
243 		bitmapRecno = firmBuild->first_bitmap_array[0];
244 
245 		//----- get the info of the first frame bitmap ----//
246 
247 		firmBitmap = firm_bitmap_array + bitmapRecno - 1;
248 
249 		firmBuild->loc_width  = firmBitmap->loc_width;
250 		firmBuild->loc_height = firmBitmap->loc_height;
251 
252 		firmBuild->min_offset_x = minOffsetX;
253 		firmBuild->min_offset_y = minOffsetY;
254 
255 		firmBuild->max_bitmap_width  = maxX2 - minOffsetX;
256 		firmBuild->max_bitmap_height = maxY2 - minOffsetY;
257 
258 		//------ set firmBuild's under construction and idle bitmap recno -----//
259 
260 		if( firmBuild->under_construction_bitmap_recno==0 )
261 			firmBuild->under_construction_bitmap_recno =	bitmapRecno;
262 
263 		if( firmBuild->idle_bitmap_recno==0 )
264 			firmBuild->idle_bitmap_recno = bitmapRecno;
265 	}
266 
267 	//------ free up the temporary array -------//
268 
269 	mem_del( firstFrameArray );
270 }
271 //--------- End of function FirmDieRes::load_firm_build ---------//
272 
273 
274 //--------- Begin of function FirmDieRes::get_build ---------//
get_build(int buildId)275 FirmBuild*	FirmDieRes::get_build(int buildId)
276 {
277 	err_when( buildId < 1 || buildId > firm_build_count);
278 	return firm_build_array+buildId-1;
279 }
280 //--------- End of function FirmDieRes::get_build ---------//
281 
282 
283 //--------- Begin of function FirmDieRes::get_bitmap ---------//
get_bitmap(int bitmapId)284 FirmDieBitmap* FirmDieRes::get_bitmap(int bitmapId)
285 {
286 	err_when( bitmapId < 1 || bitmapId > firm_bitmap_count);
287 	return firm_bitmap_array+bitmapId-1;
288 }
289 //--------- End of function FirmDieRes::get_bitmap ---------//
290 
291 
292 //--------- Begin of function FirmDie::init --------//
init(short firmId,short firmBuildId,short nationRecno,short locX1,short locY1,short locX2,short locY2)293 void FirmDie::init(short firmId, short firmBuildId, short nationRecno,
294 	short	locX1, short locY1, short locX2, short locY2)
295 {
296 	firm_id = firmId;
297 	firm_build_id = firmBuildId;
298 	nation_recno = nationRecno;
299 	loc_x1 = locX1;
300 	loc_y1 = locY1;
301 	loc_x2 = locX2;
302 	loc_y2 = locY2;
303 	frame = 1;
304 }
305 
306 // add before delete the firm
init(Firm * firmPtr)307 void FirmDie::init(Firm *firmPtr)
308 {
309 	firm_id = firmPtr->firm_id;
310 	firm_build_id = firmPtr->firm_build_id;
311 	nation_recno = firmPtr->nation_recno;
312 	loc_x1 = firmPtr->loc_x1;
313 	loc_y1 = firmPtr->loc_y1;
314 	loc_x2 = firmPtr->loc_x2;
315 	loc_y2 = firmPtr->loc_y2;
316 	frame = 1;
317 	frame_delay_count = 0;
318 }
319 
320 
321 
pre_process()322 void FirmDie::pre_process()
323 {
324 	//nothing
325 }
326 
process()327 int FirmDie::process()
328 {
329 	FirmBuild *firmBuild = firm_die_res.get_build(firm_build_id);
330 	if( ++frame_delay_count > firmBuild->frame_delay_array[frame-1])
331 	{
332 		frame_delay_count = 0;
333 		if( ++frame > 	firmBuild->frame_count)
334 		{
335 			return 1;
336 		}
337 	}
338 	return 0;
339 }
340 
341 
draw(int displayLayer)342 void FirmDie::draw(int displayLayer)
343 {
344 	// get ground dirt from firm_res
345 	FirmBuild* firmBuild = firm_res.get_build(firm_build_id);
346 
347 	if( firmBuild->ground_bitmap_recno )
348 	{
349 //		firm_res.get_bitmap(firmBuild->ground_bitmap_recno)
350 //			->draw_at(loc_x1*ZOOM_LOC_WIDTH, loc_y1*ZOOM_LOC_HEIGHT, NULL, displayLayer);
351 	}
352 
353 	//---------- draw animation now ------------//
354 
355 	firmBuild = firm_die_res.get_build(firm_build_id);
356 	FirmDieBitmap* firmBitmap;
357 
358 	int bitmapRecno, i;
359 	int firstBitmap = firmBuild->first_bitmap(frame);
360 	int bitmapCount = firmBuild->bitmap_count(frame);
361 
362 	char* colorRemapTable = game.get_color_remap_table(nation_recno, 0);
363 
364 	for( i=0, bitmapRecno=firstBitmap ; i<bitmapCount ; i++, bitmapRecno++ )
365 	{
366 		firmBitmap = firm_die_res.get_bitmap(bitmapRecno);
367 
368 		// BUGHERE : need to load bitmap into memory
369 		if( firmBitmap )
370 		{
371 			char *bitmapPtr;
372 			firmBitmap->bitmap_ptr = bitmapPtr = firm_die_res.res_bitmap.read_imported(firmBitmap->bitmap_offset);
373 			firmBitmap->width = *(short *)bitmapPtr;
374 			firmBitmap->height= *(1+(short *)bitmapPtr);
375 			firmBitmap->draw_at(loc_x1*ZOOM_LOC_WIDTH, loc_y1*ZOOM_LOC_HEIGHT, colorRemapTable, displayLayer);
376 		}
377 	}
378 }
379 
380 
FirmDieArray()381 FirmDieArray::FirmDieArray() : DynArrayB(sizeof(FirmDie),10, DEFAULT_REUSE_INTERVAL_DAYS)
382 {
383 	// nothing
384 }
385 
~FirmDieArray()386 FirmDieArray::~FirmDieArray()
387 {
388    deinit();
389 }
390 
init()391 void FirmDieArray::init()
392 {
393 	zap();
394 }
395 
deinit()396 void FirmDieArray::deinit()
397 {
398 	// nothing
399 }
400 
process()401 void FirmDieArray::process()
402 {
403 	int i, j;
404 
405 	for( i=1, j=size(); j; --j, ++i)
406 	{
407 		if( is_deleted(i) )
408 			continue;
409 
410 		FirmDie *firmDiePtr = this->operator[](i);
411 
412 		if( firmDiePtr->process() )
413 		{
414 			del(i);
415 			continue;
416 		}
417 	}
418 }
419 
420 
421 
add(FirmDie * r)422 int FirmDieArray::add(FirmDie *r)
423 {
424 	linkin(r);
425 	return recno();
426 }
427 
del(int i)428 void FirmDieArray::del(int i)
429 {
430 	linkout(i);
431 }
432 
433 
operator [](int recNo)434 FirmDie *FirmDieArray::operator[](int recNo)
435 {
436    FirmDie* firmDiePtr = (FirmDie*) get(recNo);
437 
438    if( !firmDiePtr || is_deleted(recNo) )
439       err.run( "FirmDieArray[] is deleted" );
440 
441    return firmDiePtr;
442 }
443 
is_deleted(int recNo)444 int FirmDieArray::is_deleted(int recNo)
445 {
446 	FirmDie* firmDiePtr = (FirmDie*) get(recNo);
447 	if( !firmDiePtr || firmDiePtr->firm_id == 0)
448 		return 1;
449 	return 0;
450 }
451 
452