OW_FIRE.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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 : OW_FIRE.CPP
  21. // Description: World class function related to spreading of fire
  22. // Ownership : Gilbert
  23. #include <OWORLD.h>
  24. #include <OMATRIX.h>
  25. #include <OWEATHER.h>
  26. #include <OWORLDMT.h>
  27. #include <OTERRAIN.h>
  28. #include <OUNIT.h>
  29. #include <OFIRM.h>
  30. #include <OFIRMA.h>
  31. #include <OCONFIG.h>
  32. // #### begin Gilbert 29/5 #######//
  33. #include <OSERES.h>
  34. // #### end Gilbert 29/5 #######//
  35. #include <math.h>
  36. //### begin alex 6/8 ###//
  37. #ifdef DEBUG
  38. #include <OSYS.h>
  39. #endif
  40. //#### end alex 6/8 ####//
  41. //------------ define constant ------------
  42. #define SPREAD_RATE (config.fire_spread_rate)
  43. // #define CONSUMPTION_RATE 1.0
  44. #define WIND_SPREADFIRE (config.wind_spread_fire_rate)
  45. #define FIRE_FADE_RATE (config.fire_fade_rate)
  46. // 0 - 100
  47. #define RESTORE_RATE (config.fire_restore_prob)
  48. // 0 - 20
  49. #define RAIN_SNOW_REDUCTION (config.rain_reduce_fire_rate)
  50. // ----------- Define static function ----------//
  51. static char bound_zero(char n)
  52. {
  53. if( n > 0)
  54. return n;
  55. return 0;
  56. }
  57. // ---------- Level of Location::fire_str() ---------//
  58. // 51 to 100 Highly flammable, restorable
  59. // 1 to 50 flammable, restorable
  60. // -30 to 0 flammable but the fire cannot grow, or spreaded, restorable
  61. // -50 to -31 flammable but the fire cannot grow, flammability unrestorable
  62. // -100 to -51 absolutely non-inflammable
  63. // ----------- begin of function World::init_fire ---------- //
  64. void World::init_fire()
  65. {
  66. Location *locPtr = get_loc(0,0);
  67. for( int c = max_x_loc*max_y_loc; c >0; --c, ++locPtr)
  68. {
  69. if( locPtr->has_hill())
  70. {
  71. locPtr->set_fire_src(-100);
  72. }
  73. else if( locPtr->is_wall() )
  74. {
  75. locPtr->set_fire_src(-50);
  76. }
  77. else if( locPtr->is_firm() || locPtr->is_plant() || locPtr->is_town() )
  78. {
  79. locPtr->set_fire_src(100);
  80. }
  81. else
  82. {
  83. switch(terrain_res[locPtr->terrain_id]->average_type)
  84. {
  85. case TERRAIN_OCEAN:
  86. locPtr->set_fire_src(-100);
  87. break;
  88. case TERRAIN_DARK_GRASS:
  89. locPtr->set_fire_src(100);
  90. break;
  91. case TERRAIN_LIGHT_GRASS:
  92. locPtr->set_fire_src(50);
  93. break;
  94. case TERRAIN_DARK_DIRT:
  95. locPtr->set_fire_src(-50);
  96. break;
  97. default:
  98. err_now("Undefined terrain type");
  99. }
  100. }
  101. // --------- put off fire on the map ----------//
  102. locPtr->set_fire_str(-100);
  103. }
  104. }
  105. // ----------- end of function World::init_fire ---------- //
  106. // ----------- begin of function World::spread_fire ---------- //
  107. void World::spread_fire(Weather &w)
  108. {
  109. char fireValue;
  110. int x,y;
  111. Location *locPtr;
  112. // -------- normalize wind_speed between -WIND_SPREADFIRE*SPREAD_RATE to +WIND_SPREADFIRE*SPREAD_RATE -------
  113. int windCos = int(w.wind_speed() * cos(w.wind_direct_rad()) / 100.0 * SPREAD_RATE * WIND_SPREADFIRE);
  114. int windSin = int(w.wind_speed() * sin(w.wind_direct_rad()) / 100.0 * SPREAD_RATE * WIND_SPREADFIRE);
  115. char rainSnowReduction = 0;
  116. rainSnowReduction = (w.rain_scale() > 0 || w.snow_scale() > 0) ?
  117. RAIN_SNOW_REDUCTION + (w.rain_scale() + w.snow_scale()) / 4: 0;
  118. float flameDamage = (float)config.fire_damage/ATTACK_SLOW_DOWN;
  119. // -------------update fire_level-----------
  120. for( y = scan_fire_y; y < max_y_loc; y += SCAN_FIRE_DIST)
  121. {
  122. locPtr = get_loc(scan_fire_x,y);
  123. for( x = scan_fire_x; x < max_x_loc; x += SCAN_FIRE_DIST, locPtr+=SCAN_FIRE_DIST)
  124. {
  125. char oldFireValue = fireValue = locPtr->fire_str();
  126. char flammability = locPtr->fire_src();
  127. // ------- reduce fire_level on raining or snow
  128. fireValue -= rainSnowReduction;
  129. if(fireValue < -100)
  130. fireValue = -100;
  131. if( fireValue > 0)
  132. {
  133. Unit *targetUnit;
  134. // ------- burn wall -------- //
  135. if( locPtr->is_wall() )
  136. {
  137. if( !locPtr->attack_wall(int(4.0*flameDamage)))
  138. correct_wall(x, y, 2);
  139. }
  140. // ------- burn units ---------//
  141. else if( locPtr->has_unit(UNIT_LAND))
  142. {
  143. targetUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
  144. targetUnit->hit_points -= (float)2.0*flameDamage;
  145. if( targetUnit->hit_points <= 0 )
  146. targetUnit->hit_points = (float) 0;
  147. }
  148. else if( locPtr->has_unit(UNIT_SEA))
  149. {
  150. targetUnit = unit_array[locPtr->unit_recno(UNIT_SEA)];
  151. targetUnit->hit_points -= (float)2.0*flameDamage;
  152. if( targetUnit->hit_points <= 0 )
  153. targetUnit->hit_points = (float) 0;
  154. }
  155. else if( locPtr->is_firm() && firm_res[firm_array[locPtr->firm_recno()]->firm_id]->buildable)
  156. {
  157. Firm *targetFirm = firm_array[locPtr->firm_recno()];
  158. //### begin alex 6/8 ###//
  159. #ifdef DEBUG
  160. if(debug_sim_game_type!=2)
  161. #endif
  162. //#### end alex 6/8 ####//
  163. targetFirm->hit_points -= flameDamage;
  164. if( targetFirm->hit_points <= 0)
  165. {
  166. targetFirm->hit_points = (float) 0;
  167. // ###### begin Gilbert 29/5 ########//
  168. se_res.sound(targetFirm->center_x, targetFirm->center_y, 1,
  169. 'F', targetFirm->firm_id, "DIE" );
  170. // ###### end Gilbert 29/5 ########//
  171. firm_array.del_firm(locPtr->firm_recno());
  172. }
  173. }
  174. if(SPREAD_RATE > 0)
  175. {
  176. Location *sidePtr;
  177. // spread of north square
  178. if( y>0 && (sidePtr = get_loc(x,y-1))->fire_src() >0
  179. && sidePtr->fire_str() <= 0)
  180. {
  181. sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE+windCos)));
  182. }
  183. // spread of south square
  184. if( y<max_y_loc-1 && (sidePtr = get_loc(x,y+1))->fire_src() >0
  185. && sidePtr->fire_str() <= 0)
  186. {
  187. sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE-windCos)));
  188. }
  189. // spread of east square
  190. if( x<max_x_loc-1 && (sidePtr = get_loc(x+1,y))->fire_src() >0
  191. && sidePtr->fire_str() <= 0)
  192. {
  193. sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE+windSin)));
  194. }
  195. // spread of west square
  196. if( x>0 && (sidePtr = get_loc(x-1,y))->fire_src() >0
  197. && sidePtr->fire_str() <= 0)
  198. {
  199. sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE-windSin)));
  200. }
  201. }
  202. if( flammability > 0)
  203. {
  204. // increase fire_level on its own
  205. if(++fireValue > 100)
  206. fireValue = 100;
  207. flammability -= FIRE_FADE_RATE;
  208. // if a plant on it then remove the plant, if flammability <= 0
  209. if( locPtr->is_plant() && flammability <= 0)
  210. {
  211. locPtr->remove_plant();
  212. plant_count--;
  213. }
  214. }
  215. else
  216. {
  217. // fireValue > 0, flammability < 0
  218. // putting of fire
  219. if( flammability >= -30)
  220. {
  221. fireValue-=2;
  222. flammability -= FIRE_FADE_RATE;
  223. if( flammability < -30)
  224. flammability = -30;
  225. }
  226. else if (flammability >= -50)
  227. {
  228. fireValue-=2;
  229. flammability -= FIRE_FADE_RATE;
  230. if( flammability < -50)
  231. flammability = -50;
  232. }
  233. else
  234. {
  235. fireValue = -100;
  236. flammability -= FIRE_FADE_RATE;
  237. if( flammability < -100)
  238. flammability = -100;
  239. }
  240. // if a plant on it then remove the plant, if flammability <= 0
  241. if( locPtr->is_plant() && flammability <= 0)
  242. {
  243. locPtr->remove_plant();
  244. plant_count--;
  245. }
  246. }
  247. }
  248. else
  249. {
  250. // fireValue < 0
  251. // ---------- fire_level drop slightly ----------
  252. if( fireValue > -100)
  253. fireValue--;
  254. // ---------- restore flammability ------------
  255. if( flammability >= -30 && flammability < 50 &&
  256. m.random(100) < RESTORE_RATE)
  257. flammability++;
  258. }
  259. // ---------- update new fire level -----------
  260. //-------- when fire is put off
  261. // so the fire will not light again very soon
  262. if(fireValue <= 0 && oldFireValue > 0)
  263. {
  264. fireValue -= 50;
  265. }
  266. locPtr->set_fire_str(fireValue);
  267. locPtr->set_fire_src(flammability);
  268. }
  269. }
  270. }
  271. //----------- end of function World::spread_fire ---------- //
  272. //----------- begin of function World::setup_fire ---------- //
  273. //
  274. // set a fire at location x, y
  275. // fireStrength is between 1 - 100, (default: 30)
  276. //
  277. void World::setup_fire(short x, short y, char fireStrength)
  278. {
  279. err_when( x < 0 || y < 0 || x >= max_x_loc || y >= max_y_loc);
  280. err_when(fireStrength < 0 || fireStrength > 100);
  281. Location *locPtr = get_loc(x, y);
  282. if( locPtr->fire_str() < fireStrength )
  283. {
  284. locPtr->set_fire_str(fireStrength);
  285. }
  286. }
  287. // ----------- end of function World::setup_fire ---------- //