OTORNADO.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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 : OTORNADO.CPP
  21. //Description : Object Tornado
  22. //Ownership : Gilbert
  23. #include <OSYS.h>
  24. #include <OVGA.h>
  25. #include <OUNIT.h>
  26. #include <OTORNADO.h>
  27. #include <OWORLD.h>
  28. #include <OWEATHER.h>
  29. #include <math.h>
  30. #include <OFIRM.h>
  31. #include <OFIRMA.h>
  32. #include <OSERES.h>
  33. #include <OTOWN.h>
  34. #define M_PI 3.141592654
  35. #define DAMAGE_POINT_RADIUS 32
  36. #define TORNADO_SPRITE_ID 12 // Tornado sprite in SPRITE.DBF
  37. //--------- Begin of function Tornado::init ---------//
  38. //
  39. // <short> startX, startY starting location of the tornado
  40. // <short> lifeTime time (no. of frames) the tornado survive
  41. //
  42. void Tornado::init(short startX, short startY, short lifeTime)
  43. {
  44. Sprite::init(TORNADO_SPRITE_ID, startX, startY);
  45. err_when( strcmp("TORNADO", sprite_info->sprite_code ) );
  46. attack_damage = (float) 2.0 / ATTACK_SLOW_DOWN;
  47. life_time = lifeTime;
  48. set_dir(DIR_N);
  49. cur_action = SPRITE_MOVE; // always moving
  50. dmg_offset_x = 0;
  51. dmg_offset_y = 0;
  52. }
  53. //----------- End of function Tornado::init -----------//
  54. //----------- Begin of function Tornado::pre_process ----------//
  55. void Tornado::pre_process()
  56. {
  57. double angle = m.random(32) / 16.0 * M_PI;
  58. dmg_offset_x = short(DAMAGE_POINT_RADIUS * sin(angle));
  59. dmg_offset_y = short(DAMAGE_POINT_RADIUS * cos(angle));
  60. if( --life_time <= 0)
  61. cur_action = SPRITE_DIE;
  62. }
  63. //----------- End of function Tornado::pre_process ----------//
  64. //--------- Begin of function Tornado::process_move --------//
  65. void Tornado::process_move()
  66. {
  67. int speed = weather.wind_speed() / 6;
  68. int minSpeed = magic_weather.wind_day > 0 ? 1 : 5;
  69. if( speed < minSpeed)
  70. speed = minSpeed;
  71. if( speed > 10)
  72. speed = 10;
  73. double windDir = weather.wind_direct_rad() + (m.random(31)-15)*M_PI/180.0;
  74. cur_x += short(speed * sin(windDir));
  75. cur_y -= short(speed * cos(windDir));
  76. if( ++cur_frame > cur_sprite_move()->frame_count )
  77. cur_frame = 1;
  78. // static UCHAR nextFrame[] = { 1,6,1,1,1,1,4 }; // 1->6->4->1 ...
  79. // cur_frame = nextFrame[cur_frame];
  80. hit_target();
  81. }
  82. //---------- End of function Tornado::process_move ----------//
  83. //--------- Begin of function Tornado::hit_target --------//
  84. void Tornado::hit_target()
  85. {
  86. //---- check if there is any unit in the target location ----//
  87. short damageXLoc = damage_x_loc();
  88. short damageYLoc = damage_y_loc();
  89. if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
  90. damageYLoc < 0 || damageYLoc >= world.max_y_loc)
  91. return;
  92. Location *locPtr = world.get_loc(damageXLoc, damageYLoc);
  93. Unit *targetUnit;
  94. if( locPtr->has_unit(UNIT_AIR))
  95. {
  96. targetUnit = unit_array[locPtr->unit_recno(UNIT_AIR)];
  97. targetUnit->hit_points -= 2*attack_damage;
  98. if( targetUnit->hit_points <= 0)
  99. targetUnit->hit_points = (float) 0;
  100. }
  101. if( locPtr->has_unit(UNIT_LAND))
  102. {
  103. targetUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
  104. targetUnit->hit_points -= attack_damage;
  105. if( targetUnit->hit_points <= 0)
  106. targetUnit->hit_points = (float) 0;
  107. }
  108. else if( locPtr->has_unit(UNIT_SEA))
  109. {
  110. targetUnit = unit_array[locPtr->unit_recno(UNIT_SEA)];
  111. targetUnit->hit_points -= attack_damage;
  112. if( targetUnit->hit_points <= 0)
  113. targetUnit->hit_points = (float) 0;
  114. }
  115. else
  116. {
  117. hit_building(); // pass to hit_building to check whether a building is in the location
  118. }
  119. hit_plant();
  120. hit_fire();
  121. }
  122. //---------- End of function Tornado::hit_target ----------//
  123. //------- Begin of function Tornado::hit_building -----//
  124. // building means firm or town
  125. //
  126. void Tornado::hit_building()
  127. {
  128. short damageXLoc = damage_x_loc();
  129. short damageYLoc = damage_y_loc();
  130. if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
  131. damageYLoc < 0 || damageYLoc >= world.max_y_loc)
  132. return;
  133. Location* locPtr = world.get_loc(damageXLoc, damageYLoc);
  134. // ##### begin Gilbert 30/10 #####//
  135. if(locPtr->is_firm() )
  136. // && firm_res[(firmPtr=firm_array[locPtr->firm_recno()])->firm_id]->buildable )
  137. {
  138. Firm *firmPtr = firm_array[locPtr->firm_recno()];
  139. firmPtr->hit_points -= attack_damage*2;
  140. if( firmPtr->hit_points <= 0)
  141. {
  142. firmPtr->hit_points = (float) 0;
  143. se_res.sound(firmPtr->center_x, firmPtr->center_y, 1,
  144. 'F', firmPtr->firm_id, "DIE" );
  145. firm_array.del_firm(locPtr->firm_recno());
  146. }
  147. }
  148. if( locPtr->is_town() )
  149. {
  150. Town *townPtr = town_array[locPtr->town_recno()];
  151. if( (life_time % 30) == 0 )
  152. townPtr->kill_town_people(0);
  153. }
  154. // ##### end Gilbert 30/10 #####//
  155. }
  156. //---------- End of function Tornado::hit_building ----------//
  157. //---------- Begin of function Tornado::hit_plant --------//
  158. void Tornado::hit_plant()
  159. {
  160. short damageXLoc = damage_x_loc();
  161. short damageYLoc = damage_y_loc();
  162. if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
  163. damageYLoc < 0 || damageYLoc >= world.max_y_loc)
  164. return;
  165. Location *locPtr = world.get_loc(damageXLoc, damageYLoc);
  166. if(locPtr->is_plant())
  167. {
  168. locPtr->remove_plant();
  169. // ###### begin Gilbert 24/6 ########//
  170. world.plant_count--;
  171. // ###### end Gilbert 24/6 ########//
  172. }
  173. }
  174. //---------- End of function Tornado::hit_plant --------//
  175. //---------- Begin of function Tornado::hit_fire --------//
  176. void Tornado::hit_fire()
  177. {
  178. short damageXLoc = damage_x_loc();
  179. short damageYLoc = damage_y_loc();
  180. if( damageXLoc < 0 || damageXLoc >= world.max_x_loc ||
  181. damageYLoc < 0 || damageYLoc >= world.max_y_loc)
  182. return;
  183. Location *locPtr = world.get_loc(damageXLoc, damageYLoc);
  184. if(locPtr->fire_str() > 0)
  185. {
  186. locPtr->set_fire_str(1);
  187. }
  188. }
  189. //---------- End of function Tornado::hit_plant --------//
  190. #ifdef DEBUG
  191. //------- Begin of function TornadoArray::operator[] -----//
  192. Tornado* TornadoArray::operator[](int recNo)
  193. {
  194. Tornado* tornadoPtr = (Tornado*) get_ptr(recNo);
  195. if( !tornadoPtr )
  196. err.run( "TornadoArray[] is deleted" );
  197. return tornadoPtr;
  198. }
  199. //--------- End of function TornadoArray::operator[] ----//
  200. #endif
  201. //--------- Begin of function TornadoArray::TornadoArray ------//
  202. TornadoArray::TornadoArray(int initArraySize): SpriteArray(initArraySize)
  203. {
  204. }
  205. //--------- End of function TornadoArray::TornadoArray ------//
  206. //--------- Begin of function TornadoArray::add_tornado ------//
  207. //
  208. // <short> startX, startY starting location of the tornado
  209. // <short> lifeTime time (no. of frames) the tornado survive
  210. //
  211. short TornadoArray::add_tornado(int xLoc, int yLoc, short lifeTime)
  212. {
  213. Tornado *tornadoPtr = new Tornado;
  214. tornadoPtr->init(xLoc, yLoc, lifeTime);
  215. add(tornadoPtr);
  216. return 1;
  217. }
  218. //--------- End of function TornadoArray::add_tornado ------//
  219. //--------- Begin of function TornadoArray::create_tornado ------//
  220. //
  221. // return: <int> recno of the tornado created.
  222. //
  223. short TornadoArray::create_tornado()
  224. {
  225. Tornado *tornadoPtr = new Tornado;
  226. add(tornadoPtr);
  227. return recno();
  228. }
  229. //--------- End of function TornadoArray::create_tornado ------//
  230. //--------- Begin of function TornadoArray::process ---------//
  231. void TornadoArray::process()
  232. {
  233. int i;
  234. Tornado* tornadoPtr;
  235. for (i=1; i <=size() ; i++)
  236. {
  237. tornadoPtr = (Tornado*)get_ptr(i);
  238. if( !tornadoPtr)
  239. continue;
  240. //-------- system yield ---------//
  241. if( i%20==1 )
  242. sys.yield();
  243. //------- process tornado --------//
  244. tornadoPtr->pre_process();
  245. switch(tornadoPtr->cur_action)
  246. {
  247. case SPRITE_IDLE:
  248. case SPRITE_READY_TO_MOVE:
  249. tornadoPtr->process_idle();
  250. break;
  251. case SPRITE_MOVE:
  252. tornadoPtr->process_move();
  253. break;
  254. //### begin alex 7/3 ###//
  255. case SPRITE_TURN:
  256. err_here();
  257. break;
  258. //#### end alex 7/3 ####//
  259. case SPRITE_WAIT:
  260. tornadoPtr->process_wait();
  261. break;
  262. case SPRITE_ATTACK:
  263. tornadoPtr->process_attack();
  264. break;
  265. case SPRITE_DIE:
  266. if( tornadoPtr->process_die() )
  267. del(i);
  268. break;
  269. }
  270. }
  271. }
  272. //----------- End of function TornadoArray::process -----------//
  273. //--------- Begin of function TornadoArray::draw_dot ---------//
  274. //
  275. // Draw 2x2 tiny squares on map window representing the location of the unit ---//
  276. //
  277. void TornadoArray::draw_dot()
  278. {
  279. char* vgaBufPtr = vga_back.buf_ptr();
  280. char* writePtr;
  281. Tornado* tornadoPtr;
  282. int i, mapX, mapY;
  283. int vgaBufPitch = vga_back.buf_pitch();
  284. for(i=1; i <=size() ; i++)
  285. {
  286. tornadoPtr = (Tornado*)get_ptr(i);
  287. if( !tornadoPtr )
  288. continue;
  289. mapX = MAP_X1 + tornadoPtr->cur_x_loc();
  290. mapY = MAP_Y1 + tornadoPtr->cur_y_loc();
  291. // ####### begin Gilbert 13/11 #########//
  292. if( mapX < MAP_X1 || mapX > MAP_X2 || mapY < MAP_Y1 || mapY > MAP_Y2 )
  293. return;
  294. // ####### end Gilbert 13/11 #########//
  295. writePtr = vgaBufPtr + mapY*vgaBufPitch + mapX;
  296. if( mapY > MAP_Y1)
  297. {
  298. if( mapX > MAP_X1 && writePtr[-vgaBufPitch-1] != UNEXPLORED_COLOR)
  299. writePtr[-vgaBufPitch-1] = (char)TORNADO_COLOR2;
  300. if( writePtr[-vgaBufPitch] != UNEXPLORED_COLOR)
  301. writePtr[-vgaBufPitch] = (char)TORNADO_COLOR1;
  302. if( mapX < MAP_X2 && writePtr[-vgaBufPitch+1] != UNEXPLORED_COLOR)
  303. writePtr[-vgaBufPitch+1] = (char)TORNADO_COLOR2;
  304. }
  305. if( mapX > MAP_X1 && writePtr[-1] != UNEXPLORED_COLOR)
  306. writePtr[-1] = (char)TORNADO_COLOR1;
  307. if( mapX < MAP_X2 && writePtr[1] != UNEXPLORED_COLOR)
  308. writePtr[1] = (char)TORNADO_COLOR1;
  309. if( mapY < MAP_Y2)
  310. {
  311. if( mapX > MAP_X1 && writePtr[vgaBufPitch-1] != UNEXPLORED_COLOR)
  312. writePtr[vgaBufPitch-1] = (char)TORNADO_COLOR2;
  313. if( writePtr[vgaBufPitch] != UNEXPLORED_COLOR)
  314. writePtr[vgaBufPitch] = (char)TORNADO_COLOR1;
  315. if( mapX < MAP_X2 && writePtr[vgaBufPitch+1] != UNEXPLORED_COLOR)
  316. writePtr[vgaBufPitch+1] = (char)TORNADO_COLOR2;
  317. }
  318. }
  319. }
  320. //----------- End of function UnitArray::draw_dot -----------//