OPLANT.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. //Filename : OPLANT.CPP
  21. //Description : Plant resource object
  22. //Owner : Gilbert
  23. #include <OSYS.h>
  24. #include <OVGA.h>
  25. #include <OGAMESET.h>
  26. #include <OWORLD.h>
  27. #include <OTERRAIN.h>
  28. #include <OINFO.h>
  29. #include <OPLANT.h>
  30. #include <OCONFIG.h>
  31. //---------- #define constant ------------//
  32. //#define PLANT_DB "PLANT"
  33. //#define PLANT_BITMAP_DB "PLANTBMP"
  34. //------- Begin of function PlantRes::PlantRes -----------//
  35. PlantRes::PlantRes()
  36. {
  37. init_flag=0;
  38. }
  39. //--------- End of function PlantRes::PlantRes -----------//
  40. //---------- Begin of function PlantRes::init -----------//
  41. //
  42. // This function must be called after a map is generated.
  43. //
  44. void PlantRes::init()
  45. {
  46. deinit();
  47. //----- open plant material bitmap resource file -------//
  48. String str;
  49. str = DIR_RES;
  50. // str += "I_PLANT.RES";
  51. str += "I_PLANT";
  52. str += config.terrain_set;
  53. str += ".RES";
  54. res_bitmap.init_imported(str,1); // 1-read all into buffer
  55. //------- load database information --------//
  56. load_plant_info();
  57. load_plant_bitmap();
  58. // ##### begin Gilbert 15/10 ########//
  59. plant_map_color = (char) V_DARK_GREEN;
  60. // ##### end Gilbert 15/10 ########//
  61. init_flag=1;
  62. }
  63. //---------- End of function PlantRes::init -----------//
  64. //---------- Begin of function PlantRes::deinit -----------//
  65. void PlantRes::deinit()
  66. {
  67. if( init_flag )
  68. {
  69. mem_del(plant_info_array);
  70. mem_del(plant_bitmap_array);
  71. mem_del(scan_id_array);
  72. init_flag=0;
  73. }
  74. }
  75. //---------- End of function PlantRes::deinit -----------//
  76. //------- Begin of function PlantRes::load_plant_info -------//
  77. //
  78. void PlantRes::load_plant_info()
  79. {
  80. PlantRec *plantRec;
  81. PlantInfo *plantInfo;
  82. int i;
  83. //---- read in plant count and initialize plant info array ----//
  84. String plantDbName;
  85. plantDbName = DIR_RES;
  86. plantDbName += "PLANT";
  87. plantDbName += config.terrain_set;
  88. plantDbName += ".RES";
  89. Database plantDbObj(plantDbName, 1);
  90. // Database *dbPlant = game_set.open_db(PLANT_DB);
  91. Database *dbPlant = &plantDbObj;
  92. plant_count = (short) dbPlant->rec_count();
  93. plant_info_array = (PlantInfo*) mem_add( sizeof(PlantInfo)*plant_count );
  94. memset( plant_info_array, 0, sizeof(PlantInfo) * plant_count );
  95. //---------- read in PLANT.DBF ---------//
  96. for( i=0 ; i<plant_count ; i++ )
  97. {
  98. plantRec = (PlantRec*) dbPlant->read(i+1);
  99. plantInfo = plant_info_array+i;
  100. plantInfo->climate_zone = m.atoi( plantRec->climate_zone, plantRec->ZONE_LEN );
  101. if( plantRec->tera_type1[0] == 'T' ) // town plant
  102. {
  103. plantInfo->tera_type[0] = 'T';
  104. }
  105. else
  106. {
  107. if(plantRec->tera_type1[0] != ' ')
  108. plantInfo->tera_type[0] = terrain_res.get_tera_type_id( plantRec->tera_type1 );
  109. else
  110. plantInfo->tera_type[0] = 0;
  111. }
  112. if( plantRec->tera_type2[0] == 'T' ) // town plant
  113. {
  114. plantInfo->tera_type[1] = 'T';
  115. }
  116. else
  117. {
  118. if(plantRec->tera_type2[0] != ' ')
  119. plantInfo->tera_type[1] = terrain_res.get_tera_type_id( plantRec->tera_type2 );
  120. else
  121. plantInfo->tera_type[1] = 0;
  122. }
  123. if( plantRec->tera_type3[0] == 'T' ) // town plant
  124. {
  125. plantInfo->tera_type[2] = 'T';
  126. }
  127. else
  128. {
  129. if(plantRec->tera_type3[0] != ' ')
  130. plantInfo->tera_type[2] = terrain_res.get_tera_type_id( plantRec->tera_type3 );
  131. else
  132. plantInfo->tera_type[2] = 0;
  133. }
  134. plantInfo->first_bitmap = m.atoi( plantRec->first_bitmap, plantRec->FIRST_BITMAP_LEN );
  135. plantInfo->bitmap_count = 1+m.atoi( plantRec->bitmap_count, plantRec->BITMAP_COUNT_LEN );
  136. }
  137. }
  138. //--------- End of function PlantRes::load_plant_info ---------//
  139. //------- Begin of function PlantRes::load_plant_bitmap -------//
  140. //
  141. void PlantRes::load_plant_bitmap()
  142. {
  143. PlantBitmapRec *plantBitmapRec;
  144. PlantBitmap *plantBitmap;
  145. int i;
  146. long bitmapOffset;
  147. String plantDbName;
  148. plantDbName = DIR_RES;
  149. plantDbName += "PLANTBM";
  150. plantDbName += config.terrain_set;
  151. plantDbName += ".RES";
  152. Database plantDbObj(plantDbName, 1);
  153. // Database *dbPlantBitmap = game_set.open_db(PLANT_BITMAP_DB);
  154. Database *dbPlantBitmap = &plantDbObj;
  155. plant_bitmap_count = (short) dbPlantBitmap->rec_count();
  156. plant_bitmap_array = (PlantBitmap*) mem_add( sizeof(PlantBitmap)*plant_bitmap_count );
  157. scan_id_array = (short*) mem_add( sizeof(short)*plant_bitmap_count );
  158. //-------- read in PLANTBMP.DBF -------//
  159. memset( plant_bitmap_array, 0, sizeof(PlantBitmap) * plant_bitmap_count );
  160. for( i=0 ; i<plant_bitmap_count ; i++ )
  161. {
  162. plantBitmapRec = (PlantBitmapRec*) dbPlantBitmap->read(i+1);
  163. plantBitmap = plant_bitmap_array+i;
  164. plantBitmap->size = m.atoi( plantBitmapRec->size, plantBitmapRec->SIZE_LEN );
  165. memcpy( &bitmapOffset, plantBitmapRec->bitmap_ptr, sizeof(long) );
  166. plantBitmap->bitmap_ptr = res_bitmap.read_imported(bitmapOffset);
  167. plantBitmap->bitmap_width = *((short*)plantBitmap->bitmap_ptr);
  168. plantBitmap->bitmap_height = *(((short*)plantBitmap->bitmap_ptr)+1);
  169. plantBitmap->offset_x = m.atoi( plantBitmapRec->offset_x, plantBitmapRec->OFFSET_LEN );
  170. plantBitmap->offset_y = m.atoi( plantBitmapRec->offset_y, plantBitmapRec->OFFSET_LEN );
  171. if( plantBitmapRec->town_age >= '1' && plantBitmapRec->town_age <= '9' )
  172. plantBitmap->town_age = plantBitmapRec->town_age-'0';
  173. }
  174. }
  175. //--------- End of function PlantRes::load_plant_bitmap ---------//
  176. //---------- Begin of function PlantRes::scan -----------//
  177. //
  178. // Check if any plant in resource matches the given criteria and
  179. // return the plant bitmap id. of the matched one.
  180. //
  181. // <int> climateZone - the climate zone where the plant is.
  182. // (either ZONE_TROPICAL or ZONE_TEMPERATE)
  183. // 0 - any climate zone
  184. // <int> teraType - the terrain type where the plant is.
  185. // 0 - any terrain type
  186. // <int> townAge - the age level of the town.
  187. // 0 - any town age
  188. //
  189. // return : <int> plantBitmapId - the id. of the plant bitmap.
  190. //
  191. int PlantRes::scan(int climateZone, int teraType, int townAge)
  192. {
  193. int i, j;
  194. int matchCount=0;
  195. PlantInfo* plantInfo = plant_info_array;
  196. PlantBitmap* plantBitmap = plant_bitmap_array + plantInfo->first_bitmap - 1;
  197. //-------- scan plant id. ----------//
  198. for( i=0 ; i<plant_count ; i++, plantInfo++ )
  199. {
  200. if( !climateZone || (plantInfo->climate_zone & climateZone) )
  201. {
  202. if( !teraType ||
  203. plantInfo->tera_type[0] == teraType ||
  204. plantInfo->tera_type[1] == teraType ||
  205. plantInfo->tera_type[2] == teraType )
  206. {
  207. //------ scan plant bitmap ----------//
  208. plantBitmap = plant_bitmap_array + plantInfo->first_bitmap - 1;
  209. for( j=0 ; j<plantInfo->bitmap_count ; j++, plantBitmap++ )
  210. {
  211. if( !townAge || plantBitmap->town_age == townAge || plantBitmap->town_age=='*' ) // * = wildcard type, could apply to any town age level
  212. {
  213. scan_id_array[matchCount++] = plantInfo->first_bitmap + j;
  214. err_when( matchCount > plant_bitmap_count );
  215. }
  216. }
  217. }
  218. }
  219. }
  220. //--- pick one from those plants that match the criteria ---//
  221. if( matchCount > 0 )
  222. {
  223. int plantBitmapId = scan_id_array[m.random(matchCount)];
  224. err_when( plantBitmapId < 1 || plantBitmapId > plant_bitmap_count );
  225. return plantBitmapId;
  226. }
  227. else
  228. return 0;
  229. }
  230. //---------- End of function PlantRes::scan -----------//
  231. //---------- Begin of function PlantRes::plant_recno ----------//
  232. short PlantRes::plant_recno(short bitmapId)
  233. {
  234. int i;
  235. PlantInfo *plantInfo = plant_info_array;
  236. for( i = 0; i<plant_count; ++i, plantInfo++ )
  237. if( plantInfo->first_bitmap <= bitmapId &&
  238. bitmapId < plantInfo->first_bitmap+ plantInfo->bitmap_count)
  239. return i+1;
  240. return 0;
  241. }
  242. //---------- End of function PlantRes::plant_recno ----------//
  243. #ifdef DEBUG
  244. //---------- Begin of function PlantRes::operator[] -----------//
  245. PlantInfo* PlantRes::operator[](int plantId)
  246. {
  247. err_if( plantId<1 || plantId>plant_count )
  248. err_now( "PlantRes::operator[]" );
  249. return plant_info_array+plantId-1;
  250. }
  251. //------------ End of function PlantRes::operator[] -----------//
  252. //---------- Begin of function PlantRes::get_bitmap -----------//
  253. PlantBitmap* PlantRes::get_bitmap(int bitmapId)
  254. {
  255. err_if( bitmapId<1 || bitmapId>plant_bitmap_count )
  256. err_now( "PlantRes::get_bitmap" );
  257. return plant_bitmap_array+bitmapId-1;
  258. }
  259. //------------ End of function PlantRes::get_bitmap -----------//
  260. #endif
  261. //------- Begin of function PlantBitmap::draw -----------//
  262. //
  263. // Draw the current plant on the map
  264. //
  265. void PlantBitmap::draw(int xLoc, int yLoc)
  266. {
  267. //---- get the inner position of the plant inside the location ----//
  268. Location* locPtr = world.get_loc(xLoc, yLoc);
  269. int innerX = locPtr->cargo_recno & 0xFF; // low byte - x inner position of the plant within the location
  270. int innerY = locPtr->cargo_recno >> 8; // high byte - y inner position of the plant within the location
  271. //----------- calculate absolute positions ------------//
  272. int absX1 = xLoc*ZOOM_LOC_WIDTH +innerX-ZOOM_LOC_WIDTH/2 +offset_x;
  273. int absY1 = yLoc*ZOOM_LOC_HEIGHT+innerY-ZOOM_LOC_HEIGHT/2+offset_y;
  274. int absX2 = absX1 + bitmap_width - 1;
  275. int absY2 = absY1 + bitmap_height - 1;
  276. //-------- check if the firm is within the view area --------//
  277. int x1 = absX1 - World::view_top_x;
  278. if( x1 <= -bitmap_width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area
  279. return;
  280. int y1 = absY1 - World::view_top_y;
  281. if( y1 <= -bitmap_height || y1 >= ZOOM_HEIGHT )
  282. return;
  283. //------- decide which approach to use for displaying -----//
  284. int x2 = absX2 - World::view_top_x;
  285. int y2 = absY2 - World::view_top_y;
  286. //---- only portion of the sprite is inside the view area ------//
  287. if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
  288. {
  289. vga_back.put_bitmap_area_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr,
  290. max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
  291. }
  292. //---- the whole sprite is inside the view area ------//
  293. else
  294. {
  295. vga_back.put_bitmap_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr );
  296. }
  297. }
  298. //--------- End of function PlantBitmap::draw -----------//
  299. //------- Begin of function PlantBitmap::draw_at -----------//
  300. //
  301. // Draw the plant on the zoom map, given the exact pixel position to put
  302. // the bitmap.
  303. //
  304. // <int> absBaseX, absBaseY - the absolute base (center-bottom) coordination
  305. // of the building.
  306. //
  307. // Draw the current plant on the map
  308. //
  309. void PlantBitmap::draw_at(int absBaseX, int absBaseY)
  310. {
  311. int absX1 = absBaseX - bitmap_width/2;
  312. int absY1 = absBaseY - bitmap_height;
  313. int absX2 = absX1 + bitmap_width - 1;
  314. int absY2 = absY1 + bitmap_height - 1;
  315. //-------- check if the firm is within the view area --------//
  316. int x1 = absX1 - World::view_top_x;
  317. if( x1 <= -bitmap_width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area
  318. return;
  319. int y1 = absY1 - World::view_top_y;
  320. if( y1 <= -bitmap_height || y1 >= ZOOM_HEIGHT )
  321. return;
  322. //------- decide which approach to use for displaying -----//
  323. int x2 = absX2 - World::view_top_x;
  324. int y2 = absY2 - World::view_top_y;
  325. //---- only portion of the sprite is inside the view area ------//
  326. if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
  327. {
  328. int srcX1 = 0;
  329. int srcY1 = 0;
  330. int srcX2 = bitmap_width - 1;
  331. int srcY2 = bitmap_height - 1;
  332. if( x1 < 0 ) // get a starting location towards more right
  333. srcX1 -= x1;
  334. if( y1 < 0 )
  335. srcY1 -= y1; // get a starting location towards more bottom
  336. if( x2 >= ZOOM_WIDTH )
  337. srcX2 -= x2-(ZOOM_WIDTH-1);
  338. if( y2 >= ZOOM_HEIGHT )
  339. srcY2 -= y2-(ZOOM_HEIGHT-1);
  340. vga_back.put_bitmap_area_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1,
  341. bitmap_ptr, srcX1, srcY1, srcX2, srcY2 );
  342. }
  343. //---- the whole sprite is inside the view area ------//
  344. else
  345. {
  346. vga_back.put_bitmap_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmap_ptr );
  347. }
  348. }
  349. //--------- End of function PlantBitmap::draw_at -----------//