123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- // Filename : OW_FIRE.CPP
- // Description: World class function related to spreading of fire
- // Ownership : Gilbert
- #include <OWORLD.h>
- #include <OMATRIX.h>
- #include <OWEATHER.h>
- #include <OWORLDMT.h>
- #include <OTERRAIN.h>
- #include <OUNIT.h>
- #include <OFIRM.h>
- #include <OFIRMA.h>
- #include <OCONFIG.h>
- // #### begin Gilbert 29/5 #######//
- #include <OSERES.h>
- // #### end Gilbert 29/5 #######//
- #include <math.h>
- //### begin alex 6/8 ###//
- #ifdef DEBUG
- #include <OSYS.h>
- #endif
- //#### end alex 6/8 ####//
- //------------ define constant ------------
- #define SPREAD_RATE (config.fire_spread_rate)
- // #define CONSUMPTION_RATE 1.0
- #define WIND_SPREADFIRE (config.wind_spread_fire_rate)
- #define FIRE_FADE_RATE (config.fire_fade_rate)
- // 0 - 100
- #define RESTORE_RATE (config.fire_restore_prob)
- // 0 - 20
- #define RAIN_SNOW_REDUCTION (config.rain_reduce_fire_rate)
- // ----------- Define static function ----------//
- static char bound_zero(char n)
- {
- if( n > 0)
- return n;
- return 0;
- }
- // ---------- Level of Location::fire_str() ---------//
- // 51 to 100 Highly flammable, restorable
- // 1 to 50 flammable, restorable
- // -30 to 0 flammable but the fire cannot grow, or spreaded, restorable
- // -50 to -31 flammable but the fire cannot grow, flammability unrestorable
- // -100 to -51 absolutely non-inflammable
- // ----------- begin of function World::init_fire ---------- //
- void World::init_fire()
- {
- Location *locPtr = get_loc(0,0);
- for( int c = max_x_loc*max_y_loc; c >0; --c, ++locPtr)
- {
- if( locPtr->has_hill())
- {
- locPtr->set_fire_src(-100);
- }
- else if( locPtr->is_wall() )
- {
- locPtr->set_fire_src(-50);
- }
- else if( locPtr->is_firm() || locPtr->is_plant() || locPtr->is_town() )
- {
- locPtr->set_fire_src(100);
- }
- else
- {
- switch(terrain_res[locPtr->terrain_id]->average_type)
- {
- case TERRAIN_OCEAN:
- locPtr->set_fire_src(-100);
- break;
- case TERRAIN_DARK_GRASS:
- locPtr->set_fire_src(100);
- break;
- case TERRAIN_LIGHT_GRASS:
- locPtr->set_fire_src(50);
- break;
- case TERRAIN_DARK_DIRT:
- locPtr->set_fire_src(-50);
- break;
- default:
- err_now("Undefined terrain type");
- }
- }
- // --------- put off fire on the map ----------//
- locPtr->set_fire_str(-100);
- }
- }
- // ----------- end of function World::init_fire ---------- //
- // ----------- begin of function World::spread_fire ---------- //
- void World::spread_fire(Weather &w)
- {
-
- char fireValue;
- int x,y;
- Location *locPtr;
- // -------- normalize wind_speed between -WIND_SPREADFIRE*SPREAD_RATE to +WIND_SPREADFIRE*SPREAD_RATE -------
- int windCos = int(w.wind_speed() * cos(w.wind_direct_rad()) / 100.0 * SPREAD_RATE * WIND_SPREADFIRE);
- int windSin = int(w.wind_speed() * sin(w.wind_direct_rad()) / 100.0 * SPREAD_RATE * WIND_SPREADFIRE);
- char rainSnowReduction = 0;
-
- rainSnowReduction = (w.rain_scale() > 0 || w.snow_scale() > 0) ?
- RAIN_SNOW_REDUCTION + (w.rain_scale() + w.snow_scale()) / 4: 0;
- float flameDamage = (float)config.fire_damage/ATTACK_SLOW_DOWN;
- // -------------update fire_level-----------
- for( y = scan_fire_y; y < max_y_loc; y += SCAN_FIRE_DIST)
- {
- locPtr = get_loc(scan_fire_x,y);
- for( x = scan_fire_x; x < max_x_loc; x += SCAN_FIRE_DIST, locPtr+=SCAN_FIRE_DIST)
- {
- char oldFireValue = fireValue = locPtr->fire_str();
- char flammability = locPtr->fire_src();
- // ------- reduce fire_level on raining or snow
- fireValue -= rainSnowReduction;
- if(fireValue < -100)
- fireValue = -100;
- if( fireValue > 0)
- {
- Unit *targetUnit;
- // ------- burn wall -------- //
- if( locPtr->is_wall() )
- {
- if( !locPtr->attack_wall(int(4.0*flameDamage)))
- correct_wall(x, y, 2);
- }
- // ------- burn units ---------//
- else if( locPtr->has_unit(UNIT_LAND))
- {
- targetUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
- targetUnit->hit_points -= (float)2.0*flameDamage;
- if( targetUnit->hit_points <= 0 )
- targetUnit->hit_points = (float) 0;
- }
- else if( locPtr->has_unit(UNIT_SEA))
- {
- targetUnit = unit_array[locPtr->unit_recno(UNIT_SEA)];
- targetUnit->hit_points -= (float)2.0*flameDamage;
- if( targetUnit->hit_points <= 0 )
- targetUnit->hit_points = (float) 0;
- }
- else if( locPtr->is_firm() && firm_res[firm_array[locPtr->firm_recno()]->firm_id]->buildable)
- {
- Firm *targetFirm = firm_array[locPtr->firm_recno()];
- //### begin alex 6/8 ###//
- #ifdef DEBUG
- if(debug_sim_game_type!=2)
- #endif
- //#### end alex 6/8 ####//
- targetFirm->hit_points -= flameDamage;
- if( targetFirm->hit_points <= 0)
- {
- targetFirm->hit_points = (float) 0;
- // ###### begin Gilbert 29/5 ########//
- se_res.sound(targetFirm->center_x, targetFirm->center_y, 1,
- 'F', targetFirm->firm_id, "DIE" );
- // ###### end Gilbert 29/5 ########//
- firm_array.del_firm(locPtr->firm_recno());
- }
- }
- if(SPREAD_RATE > 0)
- {
- Location *sidePtr;
- // spread of north square
- if( y>0 && (sidePtr = get_loc(x,y-1))->fire_src() >0
- && sidePtr->fire_str() <= 0)
- {
- sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE+windCos)));
- }
- // spread of south square
- if( y<max_y_loc-1 && (sidePtr = get_loc(x,y+1))->fire_src() >0
- && sidePtr->fire_str() <= 0)
- {
- sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE-windCos)));
- }
- // spread of east square
- if( x<max_x_loc-1 && (sidePtr = get_loc(x+1,y))->fire_src() >0
- && sidePtr->fire_str() <= 0)
- {
- sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE+windSin)));
- }
- // spread of west square
- if( x>0 && (sidePtr = get_loc(x-1,y))->fire_src() >0
- && sidePtr->fire_str() <= 0)
- {
- sidePtr->add_fire_str(bound_zero(char(SPREAD_RATE-windSin)));
- }
- }
- if( flammability > 0)
- {
- // increase fire_level on its own
- if(++fireValue > 100)
- fireValue = 100;
- flammability -= FIRE_FADE_RATE;
- // if a plant on it then remove the plant, if flammability <= 0
- if( locPtr->is_plant() && flammability <= 0)
- {
- locPtr->remove_plant();
- plant_count--;
- }
- }
- else
- {
- // fireValue > 0, flammability < 0
- // putting of fire
- if( flammability >= -30)
- {
- fireValue-=2;
- flammability -= FIRE_FADE_RATE;
- if( flammability < -30)
- flammability = -30;
- }
- else if (flammability >= -50)
- {
- fireValue-=2;
- flammability -= FIRE_FADE_RATE;
- if( flammability < -50)
- flammability = -50;
- }
- else
- {
- fireValue = -100;
- flammability -= FIRE_FADE_RATE;
- if( flammability < -100)
- flammability = -100;
- }
- // if a plant on it then remove the plant, if flammability <= 0
- if( locPtr->is_plant() && flammability <= 0)
- {
- locPtr->remove_plant();
- plant_count--;
- }
- }
- }
- else
- {
- // fireValue < 0
- // ---------- fire_level drop slightly ----------
- if( fireValue > -100)
- fireValue--;
-
- // ---------- restore flammability ------------
- if( flammability >= -30 && flammability < 50 &&
- m.random(100) < RESTORE_RATE)
- flammability++;
- }
- // ---------- update new fire level -----------
- //-------- when fire is put off
- // so the fire will not light again very soon
- if(fireValue <= 0 && oldFireValue > 0)
- {
- fireValue -= 50;
- }
- locPtr->set_fire_str(fireValue);
- locPtr->set_fire_src(flammability);
- }
- }
- }
- //----------- end of function World::spread_fire ---------- //
- //----------- begin of function World::setup_fire ---------- //
- //
- // set a fire at location x, y
- // fireStrength is between 1 - 100, (default: 30)
- //
- void World::setup_fire(short x, short y, char fireStrength)
- {
- err_when( x < 0 || y < 0 || x >= max_x_loc || y >= max_y_loc);
- err_when(fireStrength < 0 || fireStrength > 100);
- Location *locPtr = get_loc(x, y);
- if( locPtr->fire_str() < fireStrength )
- {
- locPtr->set_fire_str(fireStrength);
- }
- }
- // ----------- end of function World::setup_fire ---------- //
|