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    : OWALLRES.CPP
22 //Description : Wall resource object
23 //Ownership   : Gilbert
24 
25 #include <OSYS.h>
26 #include <OVGA.h>
27 #include <OFONT.h>
28 #include <OGAMESET.h>
29 #include <OWORLD.h>
30 #include <ONATION.h>
31 #include <WALLTILE.h>
32 #include <OWALLRES.h>
33 
34 //---------- #define constant ------------//
35 
36 #define WALL_DB   		"WALL"
37 
38 //------- Begin of function WallRes::WallRes -----------//
39 
WallRes()40 WallRes::WallRes()
41 {
42 	init_flag=0;
43 
44 	selected_x_loc = -1;
45 	selected_y_loc = -1;
46 }
47 //--------- End of function WallRes::WallRes -----------//
48 
49 
50 //---------- Begin of function WallRes::init -----------//
51 //
52 // This function must be called after a map is generated.
53 //
init()54 void WallRes::init()
55 {
56 	deinit();
57 
58 	//----- open wall material bitmap resource file -------//
59 
60 	String str;
61 
62 	str  = DIR_RES;
63 	str += "I_WALL.RES";
64 
65 	res_bitmap.init_imported(str,1);  // 1-read all into buffer
66 
67 	//------- load database information --------//
68 
69 	load_wall_info();
70 
71 	init_flag=1;
72 }
73 //---------- End of function WallRes::init -----------//
74 
75 
76 //---------- Begin of function WallRes::deinit -----------//
77 
deinit()78 void WallRes::deinit()
79 {
80 	if( init_flag )
81 	{
82 		mem_del(wall_info_array);
83 		mem_del(wall_index);
84 		init_flag=0;
85 	}
86 }
87 //---------- End of function WallRes::deinit -----------//
88 
89 
90 //------- Begin of function WallRes::load_wall_info -------//
91 //
load_wall_info()92 void WallRes::load_wall_info()
93 {
94 	WallRec		*wallRec;
95 	WallInfo		*wallInfo;
96 	int			i;
97 	uint32_t		bitmapOffset;
98 
99 	max_wall_id = 0;
100 
101 	//---- read in wall count and initialize wall info array ----//
102 
103 	Database *dbWall = game_set.open_db(WALL_DB);	// only one database can be opened at a time, so we read FIRM.DBF first
104 
105 	wall_count      = (short) dbWall->rec_count();
106 	wall_info_array = (WallInfo*) mem_add( sizeof(WallInfo)*wall_count );
107 
108 	memset( wall_info_array, 0, sizeof(WallInfo) * wall_count );
109 
110 	//---------- read in WALL.DBF ---------//
111 
112 	for( i=0 ; i<wall_count ; i++ )
113 	{
114 		wallRec  = (WallRec*) dbWall->read(i+1);
115 		wallInfo = wall_info_array+i;
116 
117 		wallInfo->wall_id = misc.atoi(wallRec->wall_id, wallRec->WALL_ID_LEN);
118 		wallInfo->flags = 0;
119 		if( wallRec->gate_flag == 'Y' || wallRec->gate_flag == 'y')
120 			wallInfo->set_gate();
121 		if( wallRec->trans_flag == 'Y' || wallRec->trans_flag == 'y')
122 			wallInfo->set_trans();
123 		wallInfo->offset_x = misc.atoi(wallRec->offset_x, wallRec->OFFSET_LEN);
124 		wallInfo->offset_y = misc.atoi(wallRec->offset_y, wallRec->OFFSET_LEN);
125 		wallInfo->loc_off_x = misc.atoi(wallRec->loc_off_x, wallRec->LOC_OFF_LEN);
126 		wallInfo->loc_off_y = misc.atoi(wallRec->loc_off_y, wallRec->LOC_OFF_LEN);
127 
128 		wallInfo->draw_wall_id = misc.atoi(wallRec->draw_wall, wallRec->WALL_ID_LEN);
129 
130 		memcpy( &bitmapOffset, wallRec->bitmap_ptr, sizeof(uint32_t) );
131 		wallInfo->bitmap_ptr	= res_bitmap.read_imported(bitmapOffset);
132 
133 		if( wallInfo->wall_id > max_wall_id)
134 			max_wall_id = wallInfo->wall_id;
135 	}
136 
137 	// --------- build wall_index ---------//
138 	if( max_wall_id > 0)
139 	{
140 		wall_index = (WallInfo **) mem_add(sizeof(WallInfo *) * max_wall_id);
141 		memset( wall_index, 0, sizeof(WallInfo *) * max_wall_id);
142 		for( i=0 ; i<wall_count ; i++ )
143 		{
144 			wall_index[wall_info_array[i].wall_id -1] = &wall_info_array[i];
145 		}
146 	}
147 	else
148 	{
149 		err.run("No wall database found");
150 	}
151 }
152 //--------- End of function WallRes::load_wall_info ---------//
153 
154 
155 //------- Begin of function WallRes::draw_selected -------//
156 //
draw_selected()157 void WallRes::draw_selected()
158 {
159 	if( selected_x_loc < 0 )
160 		return;
161 
162 	int x = selected_x_loc * ZOOM_LOC_WIDTH;
163 	int y = selected_y_loc * ZOOM_LOC_HEIGHT;
164 
165 	x = x - World::view_top_x + ZOOM_X1;
166 	y = y - World::view_top_y + ZOOM_Y1;
167 
168 	//------------ draw the square frame now ------------//
169 
170 	if( misc.is_touch( x, y, x, x, ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2 ) )
171 	{
172 		vga_back.rect( x, y, x+ZOOM_LOC_WIDTH-1, y+ZOOM_LOC_HEIGHT-1, 1, OWN_SELECT_FRAME_COLOR );
173 	}
174 }
175 //--------- End of function WallRes::draw_selected ---------//
176 
177 
178 //------- Begin of function WallRes::disp_info -------//
179 //
disp_info(int refreshFlag)180 void WallRes::disp_info(int refreshFlag)
181 {
182 	if( selected_x_loc < 0 )
183 		return;
184 
185 	if( refreshFlag == INFO_REPAINT )
186 	{
187 		font_san.d3_put( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+17, "Defense Wall" );
188 		vga_front.d3_panel_up( INFO_X1, INFO_Y1+20, INFO_X2, INFO_Y1+40, 1 );
189 	}
190 
191 	int x=INFO_X1+3, y=INFO_Y1+23;
192 	Location* locPtr = world.get_loc( selected_x_loc, selected_y_loc );
193 
194 	String str;
195 
196 	str  = locPtr->wall_abs_hit_point();
197 	str += " / 100";
198 
199 	font_san.field( x, y, "Hit Points",  x+80, str, INFO_X2-4, refreshFlag );
200 }
201 //--------- End of function WallRes::disp_info ---------//
202 
203 
204 //---------- Begin of function WallRes::operator[] -----------//
205 
operator [](int wallId)206 WallInfo* WallRes::operator[](int wallId)
207 {
208 	err_if( wallId<1 || wallId>max_wall_id )
209 		err_now( "WallRes::operator[]" );
210 
211 	return wall_index[wallId-1];
212 }
213 //------------ End of function WallRes::operator[] -----------//
214 
215 //------- Begin of function WallInfo::draw -----------//
216 //
217 // Draw the current wall on the map
218 //
draw(int xLoc,int yLoc,char * remapTbl)219 void WallInfo::draw(int xLoc, int yLoc, char *remapTbl)
220 {
221 	//----------- calculate absolute positions ------------//
222 	//-------- check if the wall is within the view area --------//
223 
224 	int x1 = xLoc*ZOOM_LOC_WIDTH + offset_x - World::view_top_x;
225 	int x2 = x1 + bitmap_width() -1;
226 	if( x2 < 0 || x1 >= ZOOM_WIDTH )	// out of the view area, not even a slight part of it appears in the view area
227 		return;
228 
229 	int y1 = yLoc*ZOOM_LOC_HEIGHT +offset_y - World::view_top_y;
230 	int y2 = y1 + bitmap_height() -1;
231 	if( y2 < 0 || y1 >= ZOOM_HEIGHT )
232 		return;
233 
234 	//------- decide which approach to use for displaying -----//
235 	//---- only portion of the sprite is inside the view area ------//
236 
237 	if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
238 	{
239 		if(is_trans())
240 		{
241 			if( remapTbl)
242 				vga_back.put_bitmap_area_trans_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
243 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1,
244 					remapTbl);
245 			else
246 				vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
247 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1);
248 		}
249 		else
250 		{
251 			if( remapTbl)
252 				vga_back.put_bitmap_area_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
253 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1,
254 					remapTbl);
255 			else
256 				vga_back.put_bitmap_area( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
257 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1);
258 		}
259 	}
260 
261 	//---- the whole sprite is inside the view area ------//
262 	else
263 	{
264 		if(is_trans() )
265 		{
266 			if( remapTbl)
267 				vga_back.put_bitmap_trans_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr, remapTbl);
268 			else
269 				vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr);
270 		}
271 		else
272 		{
273 			if( remapTbl)
274 				vga_back.put_bitmap_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr, remapTbl );
275 			else
276 				vga_back.put_bitmap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr);
277 		}
278 	}
279 }
280 //--------- End of function WallInfo::draw -----------//
281 
282 
283 //------- Begin of function WallInfo::draw_at -----------//
284 //
285 // Draw the wall on the zoom map, given the exact pixel position to put
286 // the bitmap.
287 //
288 // <int> absBaseX, absBaseY - the absolute base (center-bottom) coordination
289 //										of the building.
290 //
291 // Draw the current plant on the map
292 //
draw_at(int absBaseX,int absBaseY,char * remapTbl)293 void WallInfo::draw_at(int absBaseX, int absBaseY, char *remapTbl)
294 {
295 	//-------- check if the wall is within the view area --------//
296 
297 	int x1 = absBaseX - World::view_top_x;
298 	int x2 = x1 + bitmap_width() -1;
299 	if( x2 < 0 || x1 >= ZOOM_WIDTH )	// out of the view area, not even a slight part of it appears in the view area
300 		return;
301 
302 	int y1 = absBaseY - World::view_top_y;
303 	int y2 = y1 + bitmap_height() -1;
304 	if( y2 < 0 || y1 >= ZOOM_HEIGHT )
305 		return;
306 
307 	//------- decide which approach to use for displaying -----//
308 	//---- only portion of the sprite is inside the view area ------//
309 
310 	if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
311 	{
312 		// no put_bitmap_area_remap
313 		if(is_trans())
314 		{
315 			if( remapTbl)
316 				vga_back.put_bitmap_area_trans_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
317 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1,
318 					remapTbl);
319 			else
320 				vga_back.put_bitmap_area_trans( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
321 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1);
322 		}
323 		else
324 		{
325 			if( remapTbl)
326 				vga_back.put_bitmap_area_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
327 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1,
328 					remapTbl);
329 			else
330 				vga_back.put_bitmap_area( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
331 					MAX(0,x1)-x1, MAX(0,y1)-y1, MIN(ZOOM_WIDTH-1,x2)-x1, MIN(ZOOM_HEIGHT-1,y2)-y1);
332 
333 		}
334 	}
335 
336 	//---- the whole sprite is inside the view area ------//
337 	else
338 	{
339 		if(is_trans() )
340 		{
341 			if( remapTbl)
342 				vga_back.put_bitmap_trans_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr, remapTbl);
343 			else
344 				vga_back.put_bitmap_trans( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr);
345 		}
346 		else
347 		{
348 			if( remapTbl)
349 				vga_back.put_bitmap_remap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr, remapTbl );
350 			else
351 				vga_back.put_bitmap( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr);
352 		}
353 	}
354 }
355 //--------- End of function WallInfo::draw_at -----------//
356 
357